[pnetcdf] 01/01: New upstream release 1.8.0pre1

Alastair McKinstry mckinstry at moszumanska.debian.org
Wed Dec 7 12:34:48 UTC 2016


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

mckinstry pushed a commit to tag upstream/1.8.0_pre1
in repository pnetcdf.

commit 63b6948f7d1e9595cbc0feebab5201b38c12b30d
Author: Alastair McKinstry <mckinstry at debian.org>
Date:   Wed Dec 7 12:29:02 2016 +0000

    New upstream release 1.8.0pre1
---
 Makefile.in                                       |   34 +-
 README                                            |   22 +-
 RELEASE_NOTES                                     |    6 +
 aclocal.m4                                        |   92 +-
 benchmarks/C/aggregation.c                        |    6 +-
 benchmarks/C/write_block_read_column.c            |    6 +-
 benchmarks/FLASH-IO/checkpoint_ncmpi_parallel.F90 |    2 +-
 benchmarks/FLASH-IO/flash_benchmark_io.F90        |    4 +
 benchmarks/FLASH-IO/plotfile_ncmpi_parallel.F90   |    2 +-
 configure                                         |  373 ++-
 configure.in                                      |  121 +-
 examples/C/Makefile.in                            |    6 +-
 examples/C/block_cyclic.c                         |   14 +-
 examples/C/{i_varn_int64.c => bput_varn_int64.c}  |  325 +--
 examples/C/bput_varn_uint.c                       |   29 +-
 examples/C/collective_write.c                     |   14 +-
 examples/C/column_wise.c                          |   14 +-
 examples/C/create_open.c                          |   12 +-
 examples/C/depend                                 |    1 +
 examples/C/fill_mode.c                            |   12 +-
 examples/C/flexible_api.c                         |   12 +-
 examples/C/get_info.c                             |   13 +-
 examples/C/get_vara.c                             |   13 +-
 examples/C/ghost_cell.c                           |   34 +-
 examples/C/global_attributes.c                    |   17 +-
 examples/C/hints.c                                |   23 +-
 examples/C/i_varn_int64.c                         |   33 +-
 examples/C/mput.c                                 |   44 +-
 examples/C/nonblocking_write.c                    |   48 +-
 examples/C/nonblocking_write_in_def.c             |   44 +-
 examples/C/put_vara.c                             |   12 +-
 examples/C/put_varn_float.c                       |   30 +-
 examples/C/put_varn_int.c                         |   40 +-
 examples/C/req_all.c                              |   12 +-
 examples/C/transpose.c                            |   48 +-
 examples/C/vard_int.c                             |   12 +-
 examples/CXX/block_cyclic.cpp                     |    6 +-
 examples/CXX/collective_write.cpp                 |    6 +-
 examples/CXX/column_wise.cpp                      |    6 +-
 examples/CXX/fill_mode.cpp                        |    6 +-
 examples/CXX/flexible_api.cpp                     |    6 +-
 examples/CXX/get_info.cpp                         |    6 +-
 examples/CXX/get_vara.cpp                         |    6 +-
 examples/CXX/hints.cpp                            |    6 +-
 examples/CXX/nonblocking_write.cpp                |   14 +-
 examples/CXX/put_vara.cpp                         |    6 +-
 examples/CXX/put_varn_float.cpp                   |   24 +-
 examples/CXX/put_varn_int.cpp                     |   34 +-
 examples/CXX/transpose.cpp                        |    6 +-
 examples/CXX/vard_int.cpp                         |    6 +-
 examples/F77/Makefile.in                          |    4 +-
 examples/F77/block_cyclic.f                       |   11 +-
 examples/F77/bput_varn_int8.f                     |  244 +-
 examples/F77/column_wise.f                        |    8 +-
 examples/F77/fill_mode.f                          |    6 +-
 examples/F77/flexible_api.f                       |    6 +-
 examples/F77/get_info.f                           |    4 +-
 examples/F77/hints.f                              |    4 +-
 examples/F77/i_varn_real.f                        |    8 +-
 examples/F77/nonblocking_write.f                  |    8 +-
 examples/F77/put_vara.f                           |    6 +-
 examples/F77/put_varn_int.f                       |    6 +-
 examples/F77/put_varn_real.f                      |    6 +-
 examples/F77/transpose.f                          |    6 +-
 examples/F77/utils.F90                            |    4 +-
 examples/F77/vard_int.F                           |    6 +-
 examples/F90/block_cyclic.f90                     |    8 +-
 examples/F90/column_wise.f90                      |    8 +-
 examples/F90/fill_mode.f90                        |    6 +-
 examples/F90/flexible_api.f90                     |    6 +-
 examples/F90/get_info.f90                         |    4 +-
 examples/F90/hints.f90                            |    4 +-
 examples/F90/nonblocking_write.f90                |    6 +-
 examples/F90/put_var.f90                          |    6 +-
 examples/F90/put_varn_int.f90                     |    6 +-
 examples/F90/put_varn_real.f90                    |    6 +-
 examples/F90/transpose.f90                        |    6 +-
 examples/F90/utils.F90                            |    4 +-
 examples/F90/vard_int.f90                         |    6 +-
 examples/tutorial/pnetcdf-read-flexible.c         |    3 +-
 examples/tutorial/pnetcdf-read-from-master.c      |    7 +-
 examples/tutorial/pnetcdf-read-nfiles.c           |    3 +-
 examples/tutorial/pnetcdf-read-standard.c         |    3 +-
 examples/tutorial/pnetcdf-write-nb.c              |   15 +-
 examples/tutorial/pnetcdf-write-nfiles.c          |   23 +-
 macros.make.in                                    |   29 +-
 pnetcdf-config.in                                 |  319 +++
 src/lib/pnetcdf.pc.in => pnetcdf_pc.in            |   17 +-
 rules.make                                        |   14 +-
 scripts/Makefile.in                               |    6 +-
 scripts/foreach.m4                                |    8 +
 scripts/utils.m4                                  |  183 ++
 src/lib/Makefile.in                               |   25 +-
 src/lib/attr.m4                                   | 1539 +++++++------
 src/lib/bput.m4                                   |  458 +---
 src/lib/convert_swap.m4                           |  376 ++--
 src/lib/depend                                    |    1 +
 src/lib/dim.c                                     |  512 +++--
 src/lib/error.c                                   |   61 +-
 src/lib/filetype.c                                |   35 +-
 src/lib/fill.c                                    |  360 ++-
 src/lib/getput.m4                                 |  709 +-----
 src/lib/hash_func.c                               |  114 +
 src/lib/header.c                                  |  279 ++-
 src/lib/i_getput.m4                               |  834 ++-----
 src/lib/i_varn.m4                                 |  103 +-
 src/lib/m_getput_varx.m4                          |    4 +-
 src/lib/macro.h                                   |   99 +-
 src/lib/malloc.c                                  |   18 +-
 src/lib/mpincio.c                                 |  191 +-
 src/lib/mpinetcdf.c                               |  471 +++-
 src/lib/nc.c                                      |  553 +++--
 src/lib/nc.h                                      |  357 ++-
 src/lib/ncconfig.h.in                             |   28 +-
 src/lib/ncmpidtype.c                              |   23 +-
 src/lib/ncx.h                                     |  979 --------
 src/lib/ncx.m4                                    | 1444 ++++++------
 src/lib/ncx_h.m4                                  |  381 ++++
 src/lib/nonblocking.c                             | 1251 +++++-----
 src/lib/pnetcdf.h.in                              |   37 +-
 src/lib/string.c                                  |    9 +-
 src/lib/subfile.c                                 |    4 +-
 src/lib/utf8proc.c                                |   44 +-
 src/lib/utf8proc.h                                |   22 +-
 src/lib/utf8proc_data.h                           |    8 +-
 src/lib/util.c                                    |   75 +-
 src/lib/var.c                                     |  661 ++++--
 src/lib/vard.c                                    |   39 +-
 src/lib/varn.m4                                   |   92 +-
 src/libcxx/ncmpiGroup.cpp                         |    5 +-
 src/libcxx/ncmpiGroup.h                           |    4 +-
 src/libcxx/ncmpiVarAtt.cpp                        |    3 +-
 src/libf/Makefile.in                              |    5 +-
 src/libf/buildiface                               |   34 +-
 src/libf/defs                                     |  138 +-
 src/libf/mpinetcdf_impl.h                         |    4 +-
 src/libf/pnetcdf.inc.in                           |   65 +-
 src/libf/strerrnof.f                              |   10 +
 src/libf90/Makefile.in                            |    3 +-
 src/libf90/api.f90.in                             |    7 +-
 src/libf90/attributes.f90                         |   11 +-
 src/libf90/file.f90                               |   13 +-
 src/libf90/nf90_constants.f90                     |   12 +-
 src/libf90/nfmpi_constants.f90.in                 |   24 +-
 src/libf90/visibility.f90                         |    4 +-
 src/utils/ncmpidiff/ncmpidiff.c                   |   36 +-
 src/utils/ncmpidump/ncmpidump.c                   |  103 +-
 src/utils/ncmpigen/genlib.c                       |    2 +-
 src/utils/ncmpigen/main.c                         |    1 +
 src/utils/ncmpivalid/ncmpivalid.c                 |   35 +-
 src/utils/ncoffsets/ncoffsets.c                   |  106 +-
 src/utils/pnetcdf_version/Makefile.in             |    2 +-
 test/C/Makefile.in                                |   15 +-
 test/C/pres_temp_4D_rd.c                          |   59 +-
 test/C/pres_temp_4D_wr.c                          |   70 +-
 test/CXX/Makefile.in                              |    5 +-
 test/F90/f90tst_parallel.f90                      |    8 +-
 test/F90/f90tst_parallel2.f90                     |   10 +-
 test/F90/f90tst_parallel3.f90                     |    8 +-
 test/F90/f90tst_parallel4.f90                     |    8 +-
 test/cdf_format/Makefile.in                       |    5 +-
 test/common/Makefile.in                           |    7 +-
 test/common/testutils.c                           |   14 +-
 test/common/testutils.h                           |    8 +-
 test/common/testutilsf.F90                        |    4 +-
 test/fandc/Makefile.in                            |    5 +-
 test/header/Makefile.in                           |    5 +-
 test/header/header_consistency.c                  |  420 +---
 test/largefile/Makefile.in                        |    5 +-
 test/nc_test/Makefile.in                          |   35 +-
 test/nc_test/depend                               |   72 +-
 test/nc_test/error.c                              |   12 +-
 test/nc_test/error.h                              |    8 +-
 test/nc_test/nc_test.c                            |  703 +++---
 test/nc_test/test_get.m4                          | 1101 ++++++---
 test/nc_test/test_iget.m4                         | 1770 +++++++++------
 test/nc_test/test_iput.m4                         | 2146 ++++++++++--------
 test/nc_test/test_put.m4                          | 1397 +++++++-----
 test/nc_test/test_read.c                          | 1792 ---------------
 test/nc_test/test_read.m4                         | 2032 +++++++++++++++++
 test/nc_test/test_write.c                         | 2185 ------------------
 test/nc_test/test_write.m4                        | 2503 +++++++++++++++++++++
 test/nc_test/tests.h                              |  793 -------
 test/nc_test/tests.h.m4                           |  523 +++++
 test/nc_test/tst_atts3.c                          |   12 +-
 test/nc_test/tst_misc.c                           |    5 +-
 test/nc_test/util.c                               |  304 +--
 test/nf90_test/Makefile.in                        |    6 +-
 test/nf90_test/test_get.m4                        |  353 +--
 test/nf90_test/test_iget.m4                       |  345 ++-
 test/nf90_test/test_iput.m4                       |  515 +++--
 test/nf90_test/test_put.m4                        |  495 ++--
 test/nf90_test/test_read.F90                      |    7 +-
 test/nf_test/Makefile.in                          |   18 +-
 test/nf_test/test_get.m4                          |  618 +++--
 test/nf_test/test_iget.m4                         |  819 ++++---
 test/nf_test/test_iput.m4                         |  716 +++---
 test/nf_test/test_put.m4                          |  822 ++++---
 test/nf_test/test_read.F                          |   49 +-
 test/nf_test/tests.inc.in                         |    4 +-
 test/nf_test/util.F                               |   16 +-
 test/nonblocking/Makefile.in                      |    5 +-
 test/nonblocking/bput_varn_uint.c                 |  130 +-
 test/nonblocking/column_wise.c                    |   94 +-
 test/nonblocking/flexible_bput.c                  |   13 +-
 test/nonblocking/i_varn_indef.c                   |  123 +-
 test/nonblocking/i_varn_int64.c                   |  127 +-
 test/nonblocking/interleaved.c                    |   16 +-
 test/nonblocking/mcoll_testf.f90                  |    8 +-
 test/nonblocking/mcoll_testf77.f                  |    8 +-
 test/nonblocking/req_all.c                        |   53 +-
 test/nonblocking/test_bput.c                      |   38 +-
 test/nonblocking/wait_after_indep.c               |   25 +-
 test/subfile/Makefile.in                          |    5 +-
 test/testcases/Makefile.in                        |   26 +-
 test/testcases/add_var.c                          |    4 +-
 test/testcases/alignment_test.c                   |   34 +-
 test/testcases/attrf.f                            |   59 +-
 test/testcases/buftype_free.c                     |   14 +-
 test/testcases/buftype_freef.f                    |   27 +-
 test/testcases/check_type.c                       |    2 +-
 test/testcases/collective_error.c                 |   53 +-
 test/testcases/depend                             |    2 +
 test/testcases/erange_fill.m4                     |  409 ++++
 test/testcases/flexible.c                         |   12 +-
 test/testcases/flexible2.c                        |   64 +-
 test/testcases/inq_num_varsf.f90                  |   11 +-
 test/testcases/inq_recsizef.f90                   |   10 +-
 test/testcases/last_large_var.c                   |  134 +-
 test/testcases/modes.c                            |   15 +-
 test/testcases/ncmpi_vars_null_stride.c           |  226 +-
 test/testcases/put_parameter.f                    |   12 +-
 test/testcases/redef1.c                           |    3 +-
 test/testcases/scalar.c                           |  124 +
 test/testcases/test_erange.c                      |  174 +-
 test/testcases/test_vard.c                        |   35 +-
 test/testcases/test_vardf.F                       |   11 +-
 test/testcases/test_vardf90.f90                   |   10 +-
 test/testcases/varn_int.c                         |   53 +-
 test/testcases/varn_intf.f                        |   11 +-
 test/testcases/varn_real.f90                      |   10 +-
 241 files changed, 22819 insertions(+), 17737 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index 5edbea0..b910ece 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2298 2016-01-07 07:33:10Z wkliao $
+# $Id: Makefile.in 2615 2016-11-13 23:58:41Z wkliao $
 #
 # @configure_input@
 
@@ -28,13 +28,15 @@ SUBDIRS		= src \
 		  benchmarks \
 		  examples
 
-GARBAGE		=
+GARBAGE		= pnetcdf_pc
 
 DIST_GARBAGE	= config.cache \
 		  config.status \
 		  config.log \
 		  macros.make \
-		  stamp-h
+		  stamp-h \
+                  pnetcdf.pc \
+                  pnetcdf-config
 
 PACKING_LIST	= Makefile.in \
 		  aclocal.m4 \
@@ -55,7 +57,9 @@ PACKING_LIST	= Makefile.in \
 		  RELEASE_NOTES \
 		  pbs.script \
 		  cobalt.script \
-		  stamp-h.in
+		  stamp-h.in \
+                  pnetcdf_pc.in \
+                  pnetcdf-config.in
 
 PACKING_SUBDIRS	= $(SUBDIRS)
 
@@ -100,7 +104,7 @@ ptests-examples: ptests-test
 ptests-benchmarks: ptests-examples
 
 INSTALLDIRS = $(INSTALL_SUBDIRS:%=install-%)
-install: $(INSTALLDIRS)
+install: $(INSTALLDIRS) install_PKGCONFIG install_CONFIG
 	@echo '+----------------------------------------------------------------------------+'
 	@echo '|'
 	@echo '|  PnetCDF has been successfully installed under $(prefix)'
@@ -130,11 +134,29 @@ install: $(INSTALLDIRS)
 $(INSTALLDIRS): 
 	$(MAKE) $(MFLAGS) -C $(@:install-%=%) install
 
+PKGCONFIG_IN = pnetcdf_pc
+PKGCONFIG    = pnetcdf.pc
+
+install_PKGCONFIG:
+	$(SED) -e "s%INSTALL_PREFIX%${prefix}%g" $(PKGCONFIG_IN) > $(PKGCONFIG)
+	$(INSTALL) -d -m 755 $(LIBDIR)/pkgconfig
+	$(INSTALL_DATA) $(PKGCONFIG) $(LIBDIR)/pkgconfig/$(PKGCONFIG)
+
+install_CONFIG:
+	$(INSTALL) -d $(BINDIR)
+	$(INSTALL) -m 755 pnetcdf-config $(BINDIR)/pnetcdf-config
+
 UNINSTALLDIRS = $(INSTALL_SUBDIRS:%=uninstall-%)
-uninstall: $(UNINSTALLDIRS)
+uninstall: $(UNINSTALLDIRS) uninstall_PKGCONFIG uninstall_CONFIG
 $(UNINSTALLDIRS): 
 	$(MAKE) $(MFLAGS) -C $(@:uninstall-%=%) uninstall
 
+uninstall_PKGCONFIG:
+	$(RM) -f $(LIBDIR)/pkgconfig/$(PKGCONFIG)
+
+uninstall_CONFIG:
+	$(RM) -f $(BINDIR)/pnetcdf-config
+
 ################################################################################
 # Distribution:
 
diff --git a/README b/README
index ba2c0be..2e9b374 100644
--- a/README
+++ b/README
@@ -18,10 +18,10 @@ PnetCDF can use MPI-IO to achieve high-performance parallel I/O.
 More extensive installation guides can be found in file INSTALL.  Additional
 information regarding the contents of the release can be found in
 the RELEASE_NOTES file in the top-level directory.  Finally, the PnetCDF web
-site,
+sites:
     http://trac.mcs.anl.gov/projects/parallel-netcdf
     http://cucis.ece.northwestern.edu/projects/PnetCDF
-contains information on bug fixes and new releases.
+contain information on bug fixes and new releases.
 
 
 Requirements:
@@ -36,11 +36,25 @@ Requirements:
       name.   
       
     - To build parallel-netcdf you will need some additional programs:
-        - either yacc or bison
-	- either lex or flex
+        - autotools (autoconfig, autoreconf, m4, etc.)
+        - Optional:
+             - either yacc or bison
+	     - either lex or flex
       These are usually part of your operating system's development tools.
 
 
+Build recipes:
+    Several machine- and platform-specific build recipes are available.
+    - README.IBM        (BlueGene systems)
+    - README.SX         (NEC SX systems)
+    - README.CRAY       (Cray systems)
+    - README.INTEL      (Intel Compilers)
+    - README.LINUX      (GNU compilers)
+    - README.Fujitsu    (Fujitsu systems)
+    - README.K-Computer (the K computer @RIKEN)
+    - README.SGI        (SGI systems, such as Endeavour @NASA)
+
+
 Note on supporting large files and large variables.
 
     - Fortran routines will pass in a 64 bit integer for some parameters (those
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index dd4e20f..d45c769 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -2,6 +2,12 @@ Parallel NetCDF Release Notes:
 =====================================
 
 -------------------------------------
+version  1.8.0.pre1 (November 15, 2016)
+-------------------------------------
+  o The full list of updates can be found in
+    http://trac.mcs.anl.gov/projects/parallel-netcdf/browser/tags/v1-8-0pre1/sneak_peek
+
+-------------------------------------
 version  1.7.0 (March 3, 2016)
 -------------------------------------
 
diff --git a/aclocal.m4 b/aclocal.m4
index da9d2a1..95243c7 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,4 +1,4 @@
-dnl $Id: aclocal.m4 2280 2015-12-26 17:41:38Z wkliao $
+dnl $Id: aclocal.m4 2554 2016-10-14 17:26:26Z wkliao $
 dnl UD macros for netcdf configure
 
 
@@ -1725,3 +1725,93 @@ AC_DEFUN([UD_CHECK_MPI_CPP_SEEK_SET], [
    AC_LANG_POP(C++)]
 )
 
+AC_DEFUN(UD_CHECK_F77_GNU_INT,
+[
+    AC_MSG_CHECKING([for Fortran 77 GNU intrinsic INT])
+    AC_LANG_PUSH([Fortran 77])
+    AC_COMPILE_IFELSE(
+       [AC_LANG_SOURCE([
+           program main
+           implicit none
+           real r
+           integer*1 i1
+           integer*2 i2
+           integer   i4
+           integer*8 i8
+           r = 12.34
+           i1 = INT(r, 1)
+           i2 = INT(r, 2)
+           i4 = INT(r)
+           i8 = INT(r, 8)
+           end
+       ])],
+       [ac_cv_f77_gnu_int="yes"],
+       [ac_cv_f77_gnu_int="no"]
+    )
+    AC_LANG_POP([Fortran 77])
+    AC_MSG_RESULT([$ac_cv_f77_gnu_int])
+])
+
+AC_DEFUN(UD_CHECK_F77_INT1,
+[
+    AC_MSG_CHECKING([for Fortran 77 intrinsic INT1])
+    AC_LANG_PUSH([Fortran 77])
+    AC_COMPILE_IFELSE(
+       [AC_LANG_SOURCE([
+           program main
+           implicit none
+           real r
+           integer*1 i1
+           r = 12.34
+           i1 = INT1(r)
+           end
+       ])],
+       [ac_cv_f77_int1="yes"],
+       [ac_cv_f77_int1="no"]
+    )
+    AC_LANG_POP([Fortran 77])
+    AC_MSG_RESULT([$ac_cv_f77_int1])
+])
+
+AC_DEFUN(UD_CHECK_F77_INT2,
+[
+    AC_MSG_CHECKING([for Fortran 77 intrinsic INT2])
+    AC_LANG_PUSH([Fortran 77])
+    AC_COMPILE_IFELSE(
+       [AC_LANG_SOURCE([
+           program main
+           implicit none
+           real r
+           integer*2 i2
+           r = 12.34
+           i2 = INT2(r)
+           end
+       ])],
+       [ac_cv_f77_int2="yes"],
+       [ac_cv_f77_int2="no"]
+    )
+    AC_LANG_POP([Fortran 77])
+    AC_MSG_RESULT([$ac_cv_f77_int2])
+])
+
+AC_DEFUN(UD_CHECK_F77_INT8,
+[
+    AC_MSG_CHECKING([for Fortran 77 intrinsic INT8])
+    AC_LANG_PUSH([Fortran 77])
+    AC_COMPILE_IFELSE(
+       [AC_LANG_SOURCE([
+           program main
+           implicit none
+           real r
+           integer*8 i8
+           r = 12.34
+           i8 = INT8(r)
+           end
+       ])],
+       [ac_cv_f77_int8="yes"],
+       [ac_cv_f77_int8="no"]
+    )
+    AC_LANG_POP([Fortran 77])
+    AC_MSG_RESULT([$ac_cv_f77_int8])
+])
+
diff --git a/benchmarks/C/aggregation.c b/benchmarks/C/aggregation.c
index 276cdef..e298c90 100644
--- a/benchmarks/C/aggregation.c
+++ b/benchmarks/C/aggregation.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: aggregation.c 2325 2016-02-28 07:49:13Z wkliao $ */
+/* $Id: aggregation.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -107,6 +107,10 @@
  *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NVARS 5
 
 #define ERR(e) {if((e)!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(e));}
diff --git a/benchmarks/C/write_block_read_column.c b/benchmarks/C/write_block_read_column.c
index d756391..27a9d78 100644
--- a/benchmarks/C/write_block_read_column.c
+++ b/benchmarks/C/write_block_read_column.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: write_block_read_column.c 2215 2015-12-08 04:58:04Z wkliao $ */
+/* $Id: write_block_read_column.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -38,6 +38,10 @@
  *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NVARS 4
 
 #define ERR(e) {if((e)!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(e));}
diff --git a/benchmarks/FLASH-IO/checkpoint_ncmpi_parallel.F90 b/benchmarks/FLASH-IO/checkpoint_ncmpi_parallel.F90
index af7b1ad..4c92054 100644
--- a/benchmarks/FLASH-IO/checkpoint_ncmpi_parallel.F90
+++ b/benchmarks/FLASH-IO/checkpoint_ncmpi_parallel.F90
@@ -338,7 +338,7 @@
       ! set some ROMIO hints
       ! call MPI_Info_set(file_info, 'romio_no_indep_rw', 'true', err)
 
-      ! disable file offset alignment for fix-sized variables
+      ! disable file offset alignment for fixed-size variables
       call MPI_Info_set(file_info, "nc_var_align_size", "1", err)
 
       cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
diff --git a/benchmarks/FLASH-IO/flash_benchmark_io.F90 b/benchmarks/FLASH-IO/flash_benchmark_io.F90
index ce2195d..bac2afa 100644
--- a/benchmarks/FLASH-IO/flash_benchmark_io.F90
+++ b/benchmarks/FLASH-IO/flash_benchmark_io.F90
@@ -5,6 +5,10 @@
 ! performance.
 ! 
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_INTEGER8
+#endif
+
 #ifdef NAGf90Fortran
       USE F90_UNIX_ENV, only : iargc, getarg
 #endif
diff --git a/benchmarks/FLASH-IO/plotfile_ncmpi_parallel.F90 b/benchmarks/FLASH-IO/plotfile_ncmpi_parallel.F90
index 5feb6b5..c8b8d4e 100644
--- a/benchmarks/FLASH-IO/plotfile_ncmpi_parallel.F90
+++ b/benchmarks/FLASH-IO/plotfile_ncmpi_parallel.F90
@@ -377,7 +377,7 @@
       ! use some ROMIO hints
       ! call MPI_Info_set(file_info, 'romio_no_indep_rw', 'true', err)
 
-      ! disable file offset alignment for fix-sized variables
+      ! disable file offset alignment for fixed-size variables
       call MPI_Info_set(file_info, "nc_var_align_size", "1", err)
 
       cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
diff --git a/configure b/configure
index 8d78b89..1df7457 100755
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
 #! /bin/sh
-# From configure.in Id: configure.in 2341 2016-03-03 20:06:27Z wkliao .
+# From configure.in Id: configure.in 2625 2016-11-15 23:10:49Z wkliao .
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for parallel-netcdf 1.7.0.
+# Generated by GNU Autoconf 2.69 for parallel-netcdf 1.8.0.pre1.
 #
 # Report bugs to <parallel-netcdf at mcs.anl.gov>.
 #
@@ -581,8 +581,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='parallel-netcdf'
 PACKAGE_TARNAME='parallel-netcdf'
-PACKAGE_VERSION='1.7.0'
-PACKAGE_STRING='parallel-netcdf 1.7.0'
+PACKAGE_VERSION='1.8.0.pre1'
+PACKAGE_STRING='parallel-netcdf 1.8.0.pre1'
 PACKAGE_BUGREPORT='parallel-netcdf at mcs.anl.gov'
 PACKAGE_URL=''
 
@@ -636,6 +636,10 @@ BUILDDIR
 has_latex
 DVIPDF
 LATEX
+RELAX_COORD_BOUND
+ENABLE_ERANGE_FILL
+enable_erange_fill
+ENABLE_SUBFILING
 enable_subfiling
 enable_coverage
 LCOV_LIB
@@ -647,6 +651,10 @@ F90LDFLAGS
 FLDFLAGS
 F90LIBS
 UPPER_CASE_MOD
+HAVE_F77_INT8
+HAVE_F77_INT2
+HAVE_F77_INT1
+HAVE_F77_GNU_INT
 FC_MODOUT
 ac_empty
 FC_MODINC
@@ -654,8 +662,9 @@ FC_MODEXT
 SIZEOF_MPI_OFFSET
 INTENTV
 is_bigendian
+in_place_swap
 SIZEOF_MPI_AINT_IS_4
-PNC_DEBUG
+PNETCDF_DEBUG
 CPP
 RANLIB
 NMFLAGS
@@ -799,6 +808,8 @@ enable_debug
 enable_in_place_swap
 enable_coverage
 enable_subfiling
+enable_erange_fill
+enable_relax_coord_bound
 enable_file_sync
 enable_large_file_test
 '
@@ -1366,7 +1377,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures parallel-netcdf 1.7.0 to adapt to many kinds of systems.
+\`configure' configures parallel-netcdf 1.8.0.pre1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1431,7 +1442,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of parallel-netcdf 1.7.0:";;
+     short | recursive ) echo "Configuration of parallel-netcdf 1.8.0.pre1:";;
    esac
   cat <<\_ACEOF
 
@@ -1458,6 +1469,13 @@ Optional Features:
   --enable-coverage       Compile with coverage support (gcc-based only).
                           [default: disabled]
   --enable-subfiling      Enable subfiling support. [default: disabled]
+  --disable-erange-fill   Disable use of fill value when out-of-range type
+                          conversion causes NC_ERANGE error. [default:
+                          enabled]
+  --enable-relax-coord-bound
+                          Enable relaxed error NC_EINVALCOORDS to allow
+                          coordinate start argument equal to dimension size
+                          when argument count is zero. [default: disabled]
   --disable-file-sync     Disable MPI file sync if you know your file system
                           can provide data consistency. [default: enabled]
   --enable-large-file-test
@@ -1564,7 +1582,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-parallel-netcdf configure 1.7.0
+parallel-netcdf configure 1.8.0.pre1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2461,7 +2479,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by parallel-netcdf $as_me 1.7.0, which was
+It was created by parallel-netcdf $as_me 1.8.0.pre1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2853,7 +2871,7 @@ PNETCDF_VERSION_PRE=`echo ${PACKAGE_VERSION} | cut -d. -f4`
 
 PNETCDF_VERSION=${PACKAGE_VERSION}
 
-SVN_DATE="$LastChangedDate: 2016-03-03 14:06:27 -0600 (Thu, 03 Mar 2016) $"
+SVN_DATE="$LastChangedDate: 2016-11-15 17:10:49 -0600 (Tue, 15 Nov 2016) $"
 PNETCDF_RELEASE_DATE2=`echo $SVN_DATE | cut -d' ' -f2`
 PNETCDF_RELEASE_DATE=`echo $SVN_DATE | cut -d' ' -f6,7,8 | cut -d')' -f1`
 
@@ -2898,41 +2916,6 @@ $as_echo "$as_me: DEBUG: PNETCDF_RELEASE_DATE=$PNETCDF_RELEASE_DATE" >&6;}
 
 
 
-cat >>confdefs.h <<_ACEOF
-#define PNETCDF_VERSION_MAJOR $PNETCDF_VERSION_MAJOR
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PNETCDF_VERSION_MINOR $PNETCDF_VERSION_MINOR
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PNETCDF_VERSION_SUB $PNETCDF_VERSION_SUB
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PNETCDF_VERSION_PRE $PNETCDF_VERSION_PRE
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PNETCDF_VERSION "$PNETCDF_VERSION"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PNETCDF_RELEASE_DATE "$PNETCDF_RELEASE_DATE"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define CONFIGURE_ARGS_CLEAN "$CONFIGURE_ARGS_CLEAN"
-_ACEOF
-
-
 
 
 
@@ -9808,12 +9791,9 @@ else
 
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking PnetCDF debug mode" >&5
-$as_echo_n "checking PnetCDF debug mode... " >&6; }
-if test "x${debug}" = xyes; then
-   $as_echo "#define PNC_DEBUG 1" >>confdefs.h
-
 
+PNETCDF_DEBUG=0
+if test "x${debug}" = xyes; then
       for ac_header in search.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "search.h" "ac_cv_header_search_h" "$ac_includes_default"
@@ -9844,10 +9824,8 @@ done
       $as_echo "#define PNC_MALLOC_TRACE 1" >>confdefs.h
 
    fi
+   PNETCDF_DEBUG=1
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $debug" >&5
-$as_echo "$debug" >&6; }
-PNC_DEBUG=${debug}
 
 
 ac_fn_c_check_type "$LINENO" "MPI_Offset" "ac_cv_type_MPI_Offset" "#include <mpi.h>
@@ -9930,14 +9908,14 @@ _ACEOF
 
 
 if test "$ac_cv_sizeof_MPI_Offset" -lt "8"; then
-   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Unable to support CDF-5 format\"" >&5
-$as_echo "$as_me: WARNING: \"Unable to support CDF-5 format\"" >&2;};
-   enable_cdf5=no
+   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Unable to support CDF-2 and CDF-5 formats\"" >&5
+$as_echo "$as_me: WARNING: \"Unable to support CDF-2 and CDF-5 formats\"" >&2;};
+   enable_cdf_2_n_5=no
 else
 
 $as_echo "#define ENABLE_CDF5 /**/" >>confdefs.h
 
-   enable_cdf5=yes
+   enable_cdf_2_n_5=yes
 fi
 
 SIZEOF_MPI_AINT_IS_4=no
@@ -11213,6 +11191,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 fi
 
+in_place_swap=yes
 # Check whether --enable-in-place-swap was given.
 if test "${enable_in_place_swap+set}" = set; then :
   enableval=$enable_in_place_swap; in_place_swap=${enableval}
@@ -11226,6 +11205,7 @@ if test "x${in_place_swap}" = xno ; then
 
 fi
 
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5
 $as_echo_n "checking whether char is unsigned... " >&6; }
 if ${ac_cv_c_char_unsigned+:} false; then :
@@ -11826,6 +11806,39 @@ _ACEOF
 # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
 # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
 # This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned short int" >&5
+$as_echo_n "checking size of unsigned short int... " >&6; }
+if ${ac_cv_sizeof_unsigned_short_int+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned short int))" "ac_cv_sizeof_unsigned_short_int"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_unsigned_short_int" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (unsigned short int)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_unsigned_short_int=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_short_int" >&5
+$as_echo "$ac_cv_sizeof_unsigned_short_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_SHORT_INT $ac_cv_sizeof_unsigned_short_int
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned short" >&5
 $as_echo_n "checking size of unsigned short... " >&6; }
 if ${ac_cv_sizeof_unsigned_short+:} false; then :
@@ -13286,6 +13299,192 @@ $as_echo "$as_me: DEBUG: FC_MODOUT=$FC_MODOUT" >&6;}
 
 fi
 
+HAVE_F77_GNU_INT=no
+HAVE_F77_INT1=no
+HAVE_F77_INT2=no
+HAVE_F77_INT8=no
+if test "x${enable_fortran}" = xyes ; then
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran 77 GNU intrinsic INT" >&5
+$as_echo_n "checking for Fortran 77 GNU intrinsic INT... " >&6; }
+    ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+    cat > conftest.$ac_ext <<_ACEOF
+
+           program main
+           implicit none
+           real r
+           integer*1 i1
+           integer*2 i2
+           integer   i4
+           integer*8 i8
+           r = 12.34
+           i1 = INT(r, 1)
+           i2 = INT(r, 2)
+           i4 = INT(r)
+           i8 = INT(r, 8)
+           end
+
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_cv_f77_gnu_int="yes"
+else
+  ac_cv_f77_gnu_int="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_f77_gnu_int" >&5
+$as_echo "$ac_cv_f77_gnu_int" >&6; }
+
+   if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: ac_cv_f77_gnu_int=$ac_cv_f77_gnu_int" >&5
+$as_echo "$as_me: DEBUG: ac_cv_f77_gnu_int=$ac_cv_f77_gnu_int" >&6;}
+          fi
+
+
+   HAVE_F77_GNU_INT=$ac_cv_f77_gnu_int
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran 77 intrinsic INT1" >&5
+$as_echo_n "checking for Fortran 77 intrinsic INT1... " >&6; }
+    ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+    cat > conftest.$ac_ext <<_ACEOF
+
+           program main
+           implicit none
+           real r
+           integer*1 i1
+           r = 12.34
+           i1 = INT1(r)
+           end
+
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_cv_f77_int1="yes"
+else
+  ac_cv_f77_int1="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_f77_int1" >&5
+$as_echo "$ac_cv_f77_int1" >&6; }
+
+   if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: ac_cv_f77_int1=$ac_cv_f77_int1" >&5
+$as_echo "$as_me: DEBUG: ac_cv_f77_int1=$ac_cv_f77_int1" >&6;}
+          fi
+
+
+   HAVE_F77_INT1=$ac_cv_f77_int1
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran 77 intrinsic INT2" >&5
+$as_echo_n "checking for Fortran 77 intrinsic INT2... " >&6; }
+    ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+    cat > conftest.$ac_ext <<_ACEOF
+
+           program main
+           implicit none
+           real r
+           integer*2 i2
+           r = 12.34
+           i2 = INT2(r)
+           end
+
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_cv_f77_int2="yes"
+else
+  ac_cv_f77_int2="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_f77_int2" >&5
+$as_echo "$ac_cv_f77_int2" >&6; }
+
+   if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: ac_cv_f77_int2=$ac_cv_f77_int2" >&5
+$as_echo "$as_me: DEBUG: ac_cv_f77_int2=$ac_cv_f77_int2" >&6;}
+          fi
+
+
+   HAVE_F77_INT2=$ac_cv_f77_int2
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran 77 intrinsic INT8" >&5
+$as_echo_n "checking for Fortran 77 intrinsic INT8... " >&6; }
+    ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+    cat > conftest.$ac_ext <<_ACEOF
+
+           program main
+           implicit none
+           real r
+           integer*8 i8
+           r = 12.34
+           i8 = INT8(r)
+           end
+
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_cv_f77_int8="yes"
+else
+  ac_cv_f77_int8="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_f77_int8" >&5
+$as_echo "$ac_cv_f77_int8" >&6; }
+
+   if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: ac_cv_f77_int8=$ac_cv_f77_int8" >&5
+$as_echo "$as_me: DEBUG: ac_cv_f77_int8=$ac_cv_f77_int8" >&6;}
+          fi
+
+
+   HAVE_F77_INT8=$ac_cv_f77_int8
+
+fi
+
 if test "x${enable_fortran}" = xyes ; then
 
 
@@ -13596,12 +13795,48 @@ else
 
 fi
 
+
+
+ENABLE_SUBFILING=0
 if test "x$enable_subfiling" = "xyes" ; then
    $as_echo "#define ENABLE_SUBFILING 1" >>confdefs.h
 
+   ENABLE_SUBFILING=1
+fi
+
+
+# Check whether --enable-erange-fill was given.
+if test "${enable_erange_fill+set}" = set; then :
+  enableval=$enable_erange_fill; enable_erange_fill=${enableval}
+else
+  enable_erange_fill=yes
+
+fi
+
+
+
+ENABLE_ERANGE_FILL=0
+if test "x$enable_erange_fill" = "xyes" ; then
+   ENABLE_ERANGE_FILL=1
+fi
+
 
+# Check whether --enable-relax-coord-bound was given.
+if test "${enable_relax_coord_bound+set}" = set; then :
+  enableval=$enable_relax_coord_bound; enable_relax_coord_bound=${enableval}
+else
+  enable_relax_coord_bound=no
+
+fi
+
+RELAX_COORD_BOUND=0
+if test "x$enable_relax_coord_bound" = "xyes" ; then
+   $as_echo "#define RELAX_COORD_BOUND 1" >>confdefs.h
+
+   RELAX_COORD_BOUND=1
 fi
 
+
 # Extract the first word of "latex", so it can be a program name with args.
 set dummy latex; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -13779,7 +14014,7 @@ fi
 
 ac_config_headers="$ac_config_headers src/libf/nfconfig_inc"
 
-ac_config_files="$ac_config_files macros.make Makefile src/Makefile src/lib/Makefile src/lib/pnetcdf.h src/lib/pnetcdf.pc src/utils/Makefile src/utils/ncmpidump/Makefile src/utils/ncmpidiff/Makefile src/utils/ncmpigen/Makefile src/utils/ncmpivalid/Makefile src/utils/pnetcdf_version/Makefile src/utils/ncoffsets/Makefile test/Makefile test/common/Makefile test/nc_test/Makefile test/C/Makefile test/fandc/Makefile test/testcases/Makefile test/nonblocking/Makefile test/header/Makefile test/cd [...]
+ac_config_files="$ac_config_files macros.make Makefile pnetcdf_pc pnetcdf-config src/Makefile src/lib/Makefile src/lib/pnetcdf.h src/utils/Makefile src/utils/ncmpidump/Makefile src/utils/ncmpidiff/Makefile src/utils/ncmpigen/Makefile src/utils/ncmpivalid/Makefile src/utils/pnetcdf_version/Makefile src/utils/ncoffsets/Makefile test/Makefile test/common/Makefile test/nc_test/Makefile test/C/Makefile test/fandc/Makefile test/testcases/Makefile test/nonblocking/Makefile test/header/Makefile  [...]
 
 
 # The following dependency is for configure.in and configure
@@ -14300,7 +14535,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by parallel-netcdf $as_me 1.7.0, which was
+This file was extended by parallel-netcdf $as_me 1.8.0.pre1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -14362,7 +14597,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-parallel-netcdf config.status 1.7.0
+parallel-netcdf config.status 1.8.0.pre1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -14488,10 +14723,11 @@ do
     "src/libf/nfconfig_inc") CONFIG_HEADERS="$CONFIG_HEADERS src/libf/nfconfig_inc" ;;
     "macros.make") CONFIG_FILES="$CONFIG_FILES macros.make" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "pnetcdf_pc") CONFIG_FILES="$CONFIG_FILES pnetcdf_pc" ;;
+    "pnetcdf-config") CONFIG_FILES="$CONFIG_FILES pnetcdf-config" ;;
     "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
     "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;;
     "src/lib/pnetcdf.h") CONFIG_FILES="$CONFIG_FILES src/lib/pnetcdf.h" ;;
-    "src/lib/pnetcdf.pc") CONFIG_FILES="$CONFIG_FILES src/lib/pnetcdf.pc" ;;
     "src/utils/Makefile") CONFIG_FILES="$CONFIG_FILES src/utils/Makefile" ;;
     "src/utils/ncmpidump/Makefile") CONFIG_FILES="$CONFIG_FILES src/utils/ncmpidump/Makefile" ;;
     "src/utils/ncmpidiff/Makefile") CONFIG_FILES="$CONFIG_FILES src/utils/ncmpidiff/Makefile" ;;
@@ -15150,8 +15386,19 @@ echo \
               Build C++ APIs                                    - ${has_mpicxx}
               Build Fortran APIs                                - ${enable_fortran}
               Enable request aggregation in nonblocking APIs    - ${enable_aggregation}
-              Build CDF-5 support                               - ${enable_cdf5}
-              Build subfiling support                           - ${enable_subfiling}"
+              Build CDF-2 and CDF-5 support                     - ${enable_cdf_2_n_5}"
+if test "x${enable_erange_fill}" = xno; then
+   echo "\
+              Fill variables when NC_ERANGE occurs              - no"
+fi
+if test "x${enable_subfiling}" = xyes; then
+   echo "\
+              Build subfiling support                           - yes"
+fi
+if test "x${enable_relax_coord_bound}" = xyes; then
+   echo "\
+              Relax start coordinate bound check                - enabled"
+fi
 if test "x${ac_cv_c_bigendian}" = xno  && (test "x${in_place_swap}" = xno) ; then
    echo "\
               Memory in-place byte swap                         - disabled"
diff --git a/configure.in b/configure.in
index ee6984d..72f0210 100644
--- a/configure.in
+++ b/configure.in
@@ -1,10 +1,10 @@
-AC_REVISION($Id: configure.in 2341 2016-03-03 20:06:27Z wkliao $)dnl
+AC_REVISION($Id: configure.in 2625 2016-11-15 23:10:49Z wkliao $)dnl
 dnl -*- Mode: shell-script-mode; -*-
 dnl Process this file with GNU autoconf(1) to produce a configure script.
 dnl
 
 AC_PREREQ([2.59])
-AC_INIT([parallel-netcdf],[1.7.0],[parallel-netcdf at mcs.anl.gov])
+AC_INIT([parallel-netcdf],[1.8.0.pre1],[parallel-netcdf at mcs.anl.gov])
 
 dnl ncconfig.h.in will be created by autoreconf (autoheader)
 AC_CONFIG_HEADERS([src/lib/ncconfig.h])
@@ -26,7 +26,7 @@ PNETCDF_VERSION=${PACKAGE_VERSION}
 dnl Do not change the following line, It is set by SVN automatically.
 dnl It defines PNETCDF_RELEASE_DATE, a string that will be used in
 dnl ncmpi_inq_libvers() to generate release date
-SVN_DATE="$LastChangedDate: 2016-03-03 14:06:27 -0600 (Thu, 03 Mar 2016) $"
+SVN_DATE="$LastChangedDate: 2016-11-15 17:10:49 -0600 (Tue, 15 Nov 2016) $"
 PNETCDF_RELEASE_DATE2=`echo $SVN_DATE | cut -d' ' -f2`
 PNETCDF_RELEASE_DATE=`echo $SVN_DATE | cut -d' ' -f6,7,8 | cut -d')' -f1`
 
@@ -46,13 +46,13 @@ UD_MSG_DEBUG([PNETCDF_VERSION_PRE=$PNETCDF_VERSION_PRE])
 UD_MSG_DEBUG([PNETCDF_VERSION=$PNETCDF_VERSION])
 UD_MSG_DEBUG([PNETCDF_RELEASE_DATE=$PNETCDF_RELEASE_DATE])
 
-AC_DEFINE_UNQUOTED(PNETCDF_VERSION_MAJOR, $PNETCDF_VERSION_MAJOR, major version number)
-AC_DEFINE_UNQUOTED(PNETCDF_VERSION_MINOR, $PNETCDF_VERSION_MINOR, minor version number)
-AC_DEFINE_UNQUOTED(PNETCDF_VERSION_SUB, $PNETCDF_VERSION_SUB, sub version number)
-AC_DEFINE_UNQUOTED(PNETCDF_VERSION_PRE, $PNETCDF_VERSION_PRE, pre-release string)
-AC_DEFINE_UNQUOTED(PNETCDF_VERSION, ["$PNETCDF_VERSION"], full PnetCDF version string)
-AC_DEFINE_UNQUOTED(PNETCDF_RELEASE_DATE, ["$PNETCDF_RELEASE_DATE"], PnetCDF release date string)
-AC_DEFINE_UNQUOTED(CONFIGURE_ARGS_CLEAN, ["$CONFIGURE_ARGS_CLEAN"], configure command-line arguments used)
+dnl AC_DEFINE_UNQUOTED(PNETCDF_VERSION_MAJOR, $PNETCDF_VERSION_MAJOR, major version number)
+dnl AC_DEFINE_UNQUOTED(PNETCDF_VERSION_MINOR, $PNETCDF_VERSION_MINOR, minor version number)
+dnl AC_DEFINE_UNQUOTED(PNETCDF_VERSION_SUB, $PNETCDF_VERSION_SUB, sub version number)
+dnl AC_DEFINE_UNQUOTED(PNETCDF_VERSION_PRE, $PNETCDF_VERSION_PRE, pre-release string)
+dnl AC_DEFINE_UNQUOTED(PNETCDF_VERSION, ["$PNETCDF_VERSION"], full PnetCDF version string)
+dnl AC_DEFINE_UNQUOTED(PNETCDF_RELEASE_DATE, ["$PNETCDF_RELEASE_DATE"], PnetCDF release date string)
+dnl AC_DEFINE_UNQUOTED(CONFIGURE_ARGS_CLEAN, ["$CONFIGURE_ARGS_CLEAN"], configure command-line arguments used)
 
 AC_SUBST(PNETCDF_VERSION_MAJOR)
 AC_SUBST(PNETCDF_VERSION_MINOR)
@@ -81,10 +81,10 @@ AH_TEMPLATE([NO_IEEE_FLOAT],            [Does system have IEEE FLOAT])
 AH_TEMPLATE([DISABLE_FILE_SYNC],        [Define if to disable MPI_File_sync])
 AH_TEMPLATE([DISABLE_IN_PLACE_SWAP],    [Define if to disable in-place byte swap])
 AH_TEMPLATE([ENABLE_SUBFILING],         [Define if to enable subfiling feature])
-AH_TEMPLATE([PNC_DEBUG],                [Define if to enable debugging])
 AH_TEMPLATE([PNC_MALLOC_TRACE],         [Define if to enable malloc tracing])
 AH_TEMPLATE([HAVE_FUNC_MACRO],          [Define if C++ macro __func__ is defined])
 AH_TEMPLATE([HAVE_FUNCTION_MACRO],      [Define if C++ macro __FUNCTION__ is defined])
+AH_TEMPLATE([RELAX_COORD_BOUND],        [Define if relaxed coord check is enabled])
 
 dnl an option to use a customized rm command
 AC_ARG_VAR(RM, Command for deleting files or directories. default: rm)
@@ -725,10 +725,9 @@ AC_ARG_ENABLE([debug],
                      @<:@default: disabled@:>@])],
     [debug=${enableval}], [debug=no]
 )
-AC_MSG_CHECKING(PnetCDF debug mode)
-if test "x${debug}" = xyes; then
-   AC_DEFINE(PNC_DEBUG)
 
+PNETCDF_DEBUG=0
+if test "x${debug}" = xyes; then
    dnl malloc memory allocation tracing relies on tdelete and tsearch
    AC_CHECK_HEADERS([search.h])
    AC_CHECK_FUNCS([tsearch tdelete])
@@ -738,10 +737,9 @@ if test "x${debug}" = xyes; then
       (test "x${ac_cv_func_tdelete}" = xyes) ; then
       AC_DEFINE(PNC_MALLOC_TRACE)
    fi
+   PNETCDF_DEBUG=1
 fi
-AC_MSG_RESULT($debug)
-PNC_DEBUG=${debug}
-AC_SUBST(PNC_DEBUG)
+AC_SUBST(PNETCDF_DEBUG)
 
 AC_CHECK_TYPE([MPI_Offset], [], [], [#include <mpi.h>])
 if test "x${ac_cv_type_MPI_Offset}" = xyes; then
@@ -751,14 +749,14 @@ else
 fi
 AC_CHECK_SIZEOF([MPI_Aint], [], [#include <mpi.h>])
 
-dnl ok, now we know how big MPI_Offset is.  If it's less than 8 bytes 
-dnl we have to disable the new "CDF-5" (variables larger than 4gb) support
+dnl Now we know how big MPI_Offset is.  If it's less than 8 bytes 
+dnl we have to disable support for CDF-2 and CDF-5 file formats
 if test "$ac_cv_sizeof_MPI_Offset" -lt "8"; then
-   AC_MSG_WARN("Unable to support CDF-5 format");
-   enable_cdf5=no
+   AC_MSG_WARN("Unable to support CDF-2 and CDF-5 formats");
+   enable_cdf_2_n_5=no
 else
    AC_DEFINE(ENABLE_CDF5,,[Define if able to support CDF-5 file format])
-   enable_cdf5=yes
+   enable_cdf_2_n_5=yes
 fi
 
 SIZEOF_MPI_AINT_IS_4=no
@@ -853,6 +851,7 @@ if test "x${enable_fortran}" = xyes ; then
     UD_HAS_MPI_DATATYPE(MPI_COMPLEX32)
 fi
 
+in_place_swap=yes
 AC_ARG_ENABLE([in-place-swap],
     [AS_HELP_STRING([--disable-in-place-swap],
                     [Disable memory in-place byte swap on Little Endian
@@ -862,6 +861,7 @@ AC_ARG_ENABLE([in-place-swap],
 if test "x${in_place_swap}" = xno ; then
     AC_DEFINE(DISABLE_IN_PLACE_SWAP)
 fi
+AC_SUBST(in_place_swap)
 
 AC_C_CHAR_UNSIGNED
 AC_C_BIGENDIAN
@@ -891,6 +891,7 @@ AC_CHECK_SIZEOF(off_t)
 AC_CHECK_SIZEOF(signed char)
 AC_CHECK_SIZEOF(unsigned char)
 AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(unsigned short int)
 AC_CHECK_SIZEOF(unsigned short)
 AC_CHECK_SIZEOF(int)
 AC_CHECK_SIZEOF(unsigned int)
@@ -966,6 +967,30 @@ if test "x${enable_fortran}" = xyes ; then
    UD_MSG_DEBUG([FC_MODOUT=$FC_MODOUT])
 fi
 
+HAVE_F77_GNU_INT=no
+HAVE_F77_INT1=no
+HAVE_F77_INT2=no
+HAVE_F77_INT8=no
+if test "x${enable_fortran}" = xyes ; then
+   UD_CHECK_F77_GNU_INT
+   UD_MSG_DEBUG([ac_cv_f77_gnu_int=$ac_cv_f77_gnu_int])
+   HAVE_F77_GNU_INT=$ac_cv_f77_gnu_int
+   AC_SUBST(HAVE_F77_GNU_INT)
+
+   UD_CHECK_F77_INT1
+   UD_MSG_DEBUG([ac_cv_f77_int1=$ac_cv_f77_int1])
+   HAVE_F77_INT1=$ac_cv_f77_int1
+   AC_SUBST(HAVE_F77_INT1)
+   UD_CHECK_F77_INT2
+   UD_MSG_DEBUG([ac_cv_f77_int2=$ac_cv_f77_int2])
+   HAVE_F77_INT2=$ac_cv_f77_int2
+   AC_SUBST(HAVE_F77_INT2)
+   UD_CHECK_F77_INT8
+   UD_MSG_DEBUG([ac_cv_f77_int8=$ac_cv_f77_int8])
+   HAVE_F77_INT8=$ac_cv_f77_int8
+   AC_SUBST(HAVE_F77_INT8)
+fi
+
 dnl
 dnl Below is to check if a Fortran compiler produces module files with upper
 dnl case file name, eg. PNETCDF.mod. However, this does not work for Mac OSX
@@ -1093,10 +1118,42 @@ AC_ARG_ENABLE([subfiling],
                    [Enable subfiling support. @<:@default: disabled@:>@])],
    [enable_subfiling=${enableval}], [enable_subfiling=no]
 )
+AC_SUBST(enable_subfiling)
+
+ENABLE_SUBFILING=0
 if test "x$enable_subfiling" = "xyes" ; then
    AC_DEFINE(ENABLE_SUBFILING)
-   AC_SUBST(enable_subfiling)
+   ENABLE_SUBFILING=1
+fi
+AC_SUBST(ENABLE_SUBFILING)
+
+AC_ARG_ENABLE([erange-fill],
+   [AS_HELP_STRING([--disable-erange-fill],
+                   [Disable use of fill value when out-of-range type
+                    conversion causes NC_ERANGE error. @<:@default: enabled@:>@])],
+   [enable_erange_fill=${enableval}], [enable_erange_fill=yes]
+)
+AC_SUBST(enable_erange_fill)
+
+ENABLE_ERANGE_FILL=0
+if test "x$enable_erange_fill" = "xyes" ; then
+   ENABLE_ERANGE_FILL=1
+fi
+AC_SUBST(ENABLE_ERANGE_FILL)
+
+AC_ARG_ENABLE([relax-coord-bound],
+   [AS_HELP_STRING([--enable-relax-coord-bound],
+                   [Enable relaxed error NC_EINVALCOORDS to allow coordinate
+                    start argument equal to dimension size when argument
+                    count is zero. @<:@default: disabled@:>@])],
+   [enable_relax_coord_bound=${enableval}], [enable_relax_coord_bound=no]
+)
+RELAX_COORD_BOUND=0
+if test "x$enable_relax_coord_bound" = "xyes" ; then
+   AC_DEFINE(RELAX_COORD_BOUND)
+   RELAX_COORD_BOUND=1
 fi
+AC_SUBST(RELAX_COORD_BOUND)
 
 AC_PATH_PROG([LATEX],  [latex])
 AC_PATH_PROG([DVIPDF], [dvipdf])
@@ -1157,10 +1214,11 @@ AC_SUBST(SEQ_CC)
 AC_CONFIG_HEADERS([src/libf/nfconfig_inc])
 AC_CONFIG_FILES(macros.make \
                 Makefile \
+                pnetcdf_pc \
+                pnetcdf-config \
                 src/Makefile \
                 src/lib/Makefile \
                 src/lib/pnetcdf.h \
-                src/lib/pnetcdf.pc \
                 src/utils/Makefile \
                 src/utils/ncmpidump/Makefile \
                 src/utils/ncmpidiff/Makefile \
@@ -1230,8 +1288,19 @@ echo \
               Build C++ APIs                                    - ${has_mpicxx}
               Build Fortran APIs                                - ${enable_fortran}
               Enable request aggregation in nonblocking APIs    - ${enable_aggregation}
-              Build CDF-5 support                               - ${enable_cdf5}
-              Build subfiling support                           - ${enable_subfiling}"
+              Build CDF-2 and CDF-5 support                     - ${enable_cdf_2_n_5}"
+if test "x${enable_erange_fill}" = xno; then
+   echo "\
+              Fill variables when NC_ERANGE occurs              - no"
+fi
+if test "x${enable_subfiling}" = xyes; then
+   echo "\
+              Build subfiling support                           - yes"
+fi
+if test "x${enable_relax_coord_bound}" = xyes; then
+   echo "\
+              Relax start coordinate bound check                - enabled"
+fi
 if test "x${ac_cv_c_bigendian}" = xno  && (test "x${in_place_swap}" = xno) ; then
    echo "\
               Memory in-place byte swap                         - disabled"
diff --git a/examples/C/Makefile.in b/examples/C/Makefile.in
index 6c02932..e58e9be 100644
--- a/examples/C/Makefile.in
+++ b/examples/C/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2245 2015-12-20 18:39:52Z wkliao $
+# $Id: Makefile.in 2384 2016-03-30 22:20:58Z wkliao $
 #
 # @configure_input@
 
@@ -35,6 +35,7 @@ C_SRCS  = collective_write.c \
           vard_int.c \
           i_varn_int64.c \
           bput_varn_uint.c \
+          bput_varn_int64.c \
           fill_mode.c \
           ghost_cell.c \
           req_all.c
@@ -111,6 +112,9 @@ i_varn_int64: i_varn_int64.o $(LIBRARY)
 bput_varn_uint: bput_varn_uint.o $(LIBRARY)
 	$(LINK.c) $< $(LDFLAGS) $(LIBS)
 
+bput_varn_int64: bput_varn_int64.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
 fill_mode: fill_mode.o $(LIBRARY)
 	$(LINK.c) $< $(LDFLAGS) $(LIBS)
 
diff --git a/examples/C/block_cyclic.c b/examples/C/block_cyclic.c
index b5bd348..3dc3975 100644
--- a/examples/C/block_cyclic.c
+++ b/examples/C/block_cyclic.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: block_cyclic.c 2325 2016-02-28 07:49:13Z wkliao $ */
+/* $Id: block_cyclic.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example, generalized from column_wise.c, makes a number of nonblocking
@@ -74,6 +74,10 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 10
 #define NX 4
 
@@ -81,7 +85,7 @@
 #define MIN(a,b) (((a)<(b))?(a):(b))
 #endif
 
-#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -97,7 +101,7 @@ usage(char *argv0)
 int main(int argc, char** argv) {
     extern int optind;
     char *filename="testfile.nc";
-    int i, j, verbose=1, rank, nprocs, err, num_reqs;
+    int i, j, verbose=1, rank, nprocs, err, num_reqs, nerrs=0;
     int ncid, cmode, varid, dimid[2], *reqs, *sts, **buf;
     MPI_Offset myNX, G_NX, myOff, block_start, block_len;
     MPI_Offset start[2], count[2];
@@ -121,7 +125,7 @@ int main(int argc, char** argv) {
     argv += optind;
     if (argc == 1) filename = argv[0]; /* optional argument */
 
-    /* set an MPI-IO hint to disable file offset alignment for fix-sized
+    /* set an MPI-IO hint to disable file offset alignment for fixed-size
      * variables */
     MPI_Info_create(&info);
     MPI_Info_set(info, "nc_var_align_size", "1");
@@ -304,6 +308,6 @@ int main(int argc, char** argv) {
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/i_varn_int64.c b/examples/C/bput_varn_int64.c
similarity index 50%
copy from examples/C/i_varn_int64.c
copy to examples/C/bput_varn_int64.c
index 5f735b6..f34b6ea 100644
--- a/examples/C/i_varn_int64.c
+++ b/examples/C/bput_varn_int64.c
@@ -4,12 +4,11 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: i_varn_int64.c 2325 2016-02-28 07:49:13Z wkliao $ */
+/* $Id: bput_varn_int64.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * This example tests nonblocking varn APIs, including
- * ncmpi_iput_varn_longlong(), ncmpi_iget_varn_longlong(), ncmpi_iput_varn(),
- * and ncmpi_iget_varn().
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example tests nonblocking buffered write varn APIs, including
+ * ncmpi_bput_varn_longlong() and ncmpi_bput_varn(),
  * It first writes a sequence of requests with arbitrary array indices and
  * lengths to four variables of type NC_INT64, and reads back.
  *
@@ -22,8 +21,8 @@
  *    netcdf testfile {
  *    // file format: CDF-5 (big variables)
  *    dimensions:
- *             Y = 4 ;
- *             X = 10 ;
+ *             Y = 10 ;
+ *             X = 4 ;
  *    variables:
  *            int64 var0(Y, X) ;
  *            int64 var1(Y, X) ;
@@ -32,28 +31,52 @@
  *    data:
  *
  *     var0 =
- *      1, 1, 1, 3, 3, 0, 0, 2, 3, 3,
- *      0, 2, 2, 2, 1, 3, 3, 2, 2, 2,
- *      3, 3, 2, 1, 1, 1, 0, 0, 3, 3,
- *      0, 0, 0, 2, 3, 3, 3, 1, 1, 1 ;
+ *      1, 0, 3, 0,
+ *      1, 2, 3, 0,
+ *      1, 2, 2, 0,
+ *      3, 2, 1, 2,
+ *      3, 1, 1, 3,
+ *      0, 3, 1, 3,
+ *      0, 3, 0, 3,
+ *      2, 2, 0, 1,
+ *      3, 2, 3, 1,
+ *      3, 2, 3, 1 ;
  *
  *     var1 =
- *      2, 2, 2, 0, 0, 1, 1, 3, 0, 0,
- *      1, 3, 3, 3, 2, 0, 0, 3, 3, 3,
- *      0, 0, 3, 2, 2, 2, 1, 1, 0, 0,
- *      1, 1, 1, 3, 0, 0, 0, 2, 2, 2 ;
+ *      2, 1, 0, 1,
+ *      2, 3, 0, 1,
+ *      2, 3, 3, 1,
+ *      0, 3, 2, 3,
+ *      0, 2, 2, 0,
+ *      1, 0, 2, 0,
+ *      1, 0, 1, 0,
+ *      3, 3, 1, 2,
+ *      0, 3, 0, 2,
+ *      0, 3, 0, 2 ;
  *
  *     var2 =
- *      3, 3, 3, 1, 1, 2, 2, 0, 1, 1,
- *      2, 0, 0, 0, 3, 1, 1, 0, 0, 0,
- *      1, 1, 0, 3, 3, 3, 2, 2, 1, 1,
- *      2, 2, 2, 0, 1, 1, 1, 3, 3, 3 ;
+ *      3, 2, 1, 2,
+ *      3, 0, 1, 2,
+ *      3, 0, 0, 2,
+ *      1, 0, 3, 0,
+ *      1, 3, 3, 1,
+ *      2, 1, 3, 1,
+ *      2, 1, 2, 1,
+ *      0, 0, 2, 3,
+ *      1, 0, 1, 3,
+ *      1, 0, 1, 3 ;
  *
  *     var3 =
- *      0, 0, 0, 2, 2, 3, 3, 1, 2, 2,
- *      3, 1, 1, 1, 0, 2, 2, 1, 1, 1,
- *      2, 2, 1, 0, 0, 0, 3, 3, 2, 2,
- *      3, 3, 3, 1, 2, 2, 2, 0, 0, 0 ;
+ *      0, 3, 2, 3,
+ *      0, 1, 2, 3,
+ *      0, 1, 1, 3,
+ *      2, 1, 0, 1,
+ *      2, 0, 0, 2,
+ *      3, 2, 0, 2,
+ *      3, 2, 3, 2,
+ *      1, 1, 3, 0,
+ *      2, 1, 2, 0,
+ *      2, 1, 2, 0 ;
  *    }
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -64,14 +87,15 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
-#define NY 4
-#define NX 10
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
+#define NY 10
+#define NX 4
 #define NDIMS 2
 
-#define ERR \
-    if (err != NC_NOERR) { \
-        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
-    }
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 #define ERRS(n,a) { \
     int _i; \
@@ -79,6 +103,7 @@
         if ((a)[_i] != NC_NOERR) { \
             printf("Error at line=%d: err[%d] %s\n", __LINE__, _i, \
                    ncmpi_strerror((a)[_i])); \
+                   nerrs++; \
         } \
     } \
 }
@@ -115,47 +140,50 @@ usage(char *argv0)
     fprintf(stderr, help, argv0);
 }
 
-static void check_contents(int ncid, int *varid)
+static int check_contents(int ncid, int *varid)
 {
-    int i, j, err;
-    long long expected[4][NY*NX] = {{1, 1, 1, 3, 3, 0, 0, 2, 3, 3,
-                                     0, 2, 2, 2, 1, 3, 3, 2, 2, 2,
-                                     3, 3, 2, 1, 1, 1, 0, 0, 3, 3,
-                                     0, 0, 0, 2, 3, 3, 3, 1, 1, 1},
-                                    {2, 2, 2, 0, 0, 1, 1, 3, 0, 0,
-                                     1, 3, 3, 3, 2, 0, 0, 3, 3, 3,
-                                     0, 0, 3, 2, 2, 2, 1, 1, 0, 0,
-                                     1, 1, 1, 3, 0, 0, 0, 2, 2, 2},
-                                    {3, 3, 3, 1, 1, 2, 2, 0, 1, 1,
-                                     2, 0, 0, 0, 3, 1, 1, 0, 0, 0,
-                                     1, 1, 0, 3, 3, 3, 2, 2, 1, 1,
-                                     2, 2, 2, 0, 1, 1, 1, 3, 3, 3},
-                                    {0, 0, 0, 2, 2, 3, 3, 1, 2, 2,
-                                     3, 1, 1, 1, 0, 2, 2, 1, 1, 1,
-                                     2, 2, 1, 0, 0, 0, 3, 3, 2, 2,
-                                     3, 3, 3, 1, 2, 2, 2, 0, 0, 0}};
-
-    long long *r_buffer = (long long*) malloc(NY*NX * sizeof(long long));
+    int i, j, err, nerrs=0;
+    long long expected[4][NY*NX] = {{1, 0, 3, 0, 1, 2, 3, 0, 1, 2,
+                                     2, 0, 3, 2, 1, 2, 3, 1, 1, 3,
+                                     0, 3, 1, 3, 0, 3, 0, 3, 2, 2,
+                                     0, 1, 3, 2, 3, 1, 3, 2, 3, 1},
+                                    {2, 1, 0, 1, 2, 3, 0, 1, 2, 3,
+                                     3, 1, 0, 3, 2, 3, 0, 2, 2, 0,
+                                     1, 0, 2, 0, 1, 0, 1, 0, 3, 3,
+                                     1, 2, 0, 3, 0, 2, 0, 3, 0, 2},
+                                    {3, 2, 1, 2, 3, 0, 1, 2, 3, 0,
+                                     0, 2, 1, 0, 3, 0, 1, 3, 3, 1,
+                                     2, 1, 3, 1, 2, 1, 2, 1, 0, 0,
+                                     2, 3, 1, 0, 1, 3, 1, 0, 1, 3},
+                                    {0, 3, 2, 3, 0, 1, 2, 3, 0, 1,
+                                     1, 3, 2, 1, 0, 1, 2, 0, 0, 2,
+                                     3, 2, 0, 2, 3, 2, 3, 2, 1, 1,
+                                     3, 0, 2, 1, 2, 0, 2, 1, 2, 0}};
+
+    long long *r_buffer = (long long*) malloc(NY*NX*sizeof(long long));
 
     for (i=0; i<4; i++) {
-        for (j=0; j<NY*NX; j++) r_buffer[j] = -1;
+        for (j=0; j<NY*NX; j++) r_buffer[j] = 99999;
         err = ncmpi_get_var_longlong_all(ncid, varid[i], r_buffer);
         ERR
 
         /* check if the contents of buf are expected */
         for (j=0; j<NY*NX; j++)
-            if (r_buffer[j] != expected[i][j])
+            if (r_buffer[j] != expected[i][j]) {
                 printf("Expected file contents [%d][%d]=%lld, but got %lld\n",
                        i,j,expected[i][j],r_buffer[j]);
+                nerrs++;
+            }
     }
     free(r_buffer);
+    return nerrs;
 }
 
 int main(int argc, char** argv)
 {
     extern int optind;
-    char *filename="testfile.nc", exec[128];
-    int i, j, k, n, rank, nprocs, verbose=1, err;
+    char *filename="testfile.nc", exec[256];
+    int i, j, k, n, rank, nprocs, verbose=1, err, nerrs=0;
     int ncid, cmode, varid[4], dimid[2], nreqs, reqs[4], sts[4];
     long long *buffer[4];
     int num_segs[4], req_lens[4];
@@ -184,7 +212,7 @@ int main(int argc, char** argv)
     if (nprocs != 4 && rank == 0 && verbose)
         printf("Warning: %s is intended to run on 4 processes\n",exec);
 
-    /* set an MPI-IO hint to disable file offset alignment for fix-sized
+    /* set an MPI-IO hint to disable file offset alignment for fixed-size
      * variables */
     MPI_Info_create(&info);
     MPI_Info_set(info, "nc_var_align_size", "1");
@@ -206,59 +234,101 @@ int main(int argc, char** argv)
     err = ncmpi_enddef(ncid); ERR
 
     /* allocate space for starts and counts */
-    starts = calloc_3D(4, 6, NDIMS);
-    counts = calloc_3D(4, 6, NDIMS);
+    starts = calloc_3D(4, 13, NDIMS);
+    counts = calloc_3D(4, 13, NDIMS);
 
     n = rank % 4;
-    num_segs[n] = 4; /* number of segments for this request */
-    starts[n][0][0]=0; starts[n][0][1]=5; counts[n][0][0]=1; counts[n][0][1]=2;
-    starts[n][1][0]=1; starts[n][1][1]=0; counts[n][1][0]=1; counts[n][1][1]=1;
-    starts[n][2][0]=2; starts[n][2][1]=6; counts[n][2][0]=1; counts[n][2][1]=2;
-    starts[n][3][0]=3; starts[n][3][1]=0; counts[n][3][0]=1; counts[n][3][1]=3;
+    num_segs[n] = 8; /* number of segments for this request */
+    starts[n][0][0]=0; starts[n][0][1]=1; counts[n][0][0]=1; counts[n][0][1]=1;
+    starts[n][1][0]=0; starts[n][1][1]=3; counts[n][1][0]=1; counts[n][1][1]=1;
+    starts[n][2][0]=1; starts[n][2][1]=3; counts[n][2][0]=1; counts[n][2][1]=1;
+    starts[n][3][0]=2; starts[n][3][1]=3; counts[n][3][0]=1; counts[n][3][1]=1;
+    starts[n][4][0]=5; starts[n][4][1]=0; counts[n][4][0]=1; counts[n][4][1]=1;
+    starts[n][5][0]=6; starts[n][5][1]=0; counts[n][5][0]=1; counts[n][5][1]=1;
+    starts[n][6][0]=6; starts[n][6][1]=2; counts[n][6][0]=1; counts[n][6][1]=1;
+    starts[n][7][0]=7; starts[n][7][1]=2; counts[n][7][0]=1; counts[n][7][1]=1;
     /* starts[n][][] n_counts[n][][] indicate the following: ("-" means skip)
-              -  -  -  -  -  X  X  -  -  - 
-              X  -  -  -  -  -  -  -  -  - 
-              -  -  -  -  -  -  X  X  -  - 
-              X  X  X  -  -  -  -  -  -  - 
+              _  X  _  X
+              _  _  _  X
+              _  _  _  X
+              _  _  _  _
+              _  _  _  _
+              X  _  _  _
+              X  _  X  _
+              _  _  X  _
+              _  _  _  _
+              _  _  _  _
      */
     n = (rank+1) % 4;
-    num_segs[n] = 6; /* number of segments for this request */
-    starts[n][0][0]=0; starts[n][0][1]=3; counts[n][0][0]=1; counts[n][0][1]=2;
-    starts[n][1][0]=0; starts[n][1][1]=8; counts[n][1][0]=1; counts[n][1][1]=2;
-    starts[n][2][0]=1; starts[n][2][1]=5; counts[n][2][0]=1; counts[n][2][1]=2;
-    starts[n][3][0]=2; starts[n][3][1]=0; counts[n][3][0]=1; counts[n][3][1]=2;
-    starts[n][4][0]=2; starts[n][4][1]=8; counts[n][4][0]=1; counts[n][4][1]=2;
-    starts[n][5][0]=3; starts[n][5][1]=4; counts[n][5][0]=1; counts[n][5][1]=3;
+    num_segs[n] = 13; /* number of segments for this request */
+    starts[n][ 0][0]=0;starts[n][ 0][1]=2;counts[n][ 0][0]=1;counts[n][ 0][1]=1;
+    starts[n][ 1][0]=1;starts[n][ 1][1]=2;counts[n][ 1][0]=1;counts[n][ 1][1]=1;
+    starts[n][ 2][0]=3;starts[n][ 2][1]=0;counts[n][ 2][0]=1;counts[n][ 2][1]=1;
+    starts[n][ 3][0]=4;starts[n][ 3][1]=0;counts[n][ 3][0]=1;counts[n][ 3][1]=1;
+    starts[n][ 4][0]=4;starts[n][ 4][1]=3;counts[n][ 4][0]=1;counts[n][ 4][1]=1;
+    starts[n][ 5][0]=5;starts[n][ 5][1]=1;counts[n][ 5][0]=1;counts[n][ 5][1]=1;
+    starts[n][ 6][0]=5;starts[n][ 6][1]=3;counts[n][ 6][0]=1;counts[n][ 6][1]=1;
+    starts[n][ 7][0]=6;starts[n][ 7][1]=1;counts[n][ 7][0]=1;counts[n][ 7][1]=1;
+    starts[n][ 8][0]=6;starts[n][ 8][1]=3;counts[n][ 8][0]=1;counts[n][ 8][1]=1;
+    starts[n][ 9][0]=8;starts[n][ 9][1]=0;counts[n][ 9][0]=1;counts[n][ 9][1]=1;
+    starts[n][10][0]=8;starts[n][10][1]=2;counts[n][10][0]=1;counts[n][10][1]=1;
+    starts[n][11][0]=9;starts[n][11][1]=0;counts[n][11][0]=1;counts[n][11][1]=1;
+    starts[n][12][0]=9;starts[n][12][1]=2;counts[n][12][0]=1;counts[n][12][1]=1;
     /* starts[n][][] counts[n][][] indicate the following pattern.
-              -  -  -  X  X  -  -  -  X  X 
-              -  -  -  -  -  X  X  -  -  - 
-              X  X  -  -  -  -  -  -  X  X 
-              -  -  -  -  X  X  X  -  -  - 
+              _  _  X  _
+              _  _  X  _
+              _  _  _  _
+              X  _  _  _
+              X  _  _  X
+              _  X  _  X
+              _  X  _  X
+              _  _  _  _
+              X  _  X  _
+              X  _  X  _
      */
     n = (rank+2) % 4;
-    num_segs[n] = 5; /* number of segments for this request */
-    starts[n][0][0]=0; starts[n][0][1]=7; counts[n][0][0]=1; counts[n][0][1]=1;
-    starts[n][1][0]=1; starts[n][1][1]=1; counts[n][1][0]=1; counts[n][1][1]=3;
-    starts[n][2][0]=1; starts[n][2][1]=7; counts[n][2][0]=1; counts[n][2][1]=3;
-    starts[n][3][0]=2; starts[n][3][1]=2; counts[n][3][0]=1; counts[n][3][1]=1;
-    starts[n][4][0]=3; starts[n][4][1]=3; counts[n][4][0]=1; counts[n][4][1]=1;
+    num_segs[n] = 7; /* number of segments for this request */
+    starts[n][0][0]=1; starts[n][0][1]=1; counts[n][0][0]=1; counts[n][0][1]=1;
+    starts[n][1][0]=2; starts[n][1][1]=1; counts[n][1][0]=1; counts[n][1][1]=2;
+    starts[n][2][0]=3; starts[n][2][1]=1; counts[n][2][0]=1; counts[n][2][1]=1;
+    starts[n][3][0]=3; starts[n][3][1]=3; counts[n][3][0]=1; counts[n][3][1]=1;
+    starts[n][4][0]=7; starts[n][4][1]=0; counts[n][4][0]=1; counts[n][4][1]=2;
+    starts[n][5][0]=8; starts[n][5][1]=1; counts[n][5][0]=1; counts[n][5][1]=1;
+    starts[n][6][0]=9; starts[n][6][1]=1; counts[n][6][0]=1; counts[n][6][1]=1;
     /* starts[n][][] counts[n][][] indicate the following pattern.
-              -  -  -  -  -  -  -  X  -  - 
-              -  X  X  X  -  -  -  X  X  X 
-              -  -  X  -  -  -  -  -  -  - 
-              -  -  -  X  -  -  -  -  -  - 
+              _  _  _  _
+              _  X  _  _
+              _  X  X  _
+              _  X  _  X
+              _  _  _  _
+              _  _  _  _
+              _  _  _  _
+              X  X  _  _
+              _  X  _  _
+              _  X  _  _
      */
     n = (rank+3) % 4;
-    num_segs[n] = 4; /* number of segments for this request */
-    starts[n][0][0]=0; starts[n][0][1]=0; counts[n][0][0]=1; counts[n][0][1]=3;
-    starts[n][1][0]=1; starts[n][1][1]=4; counts[n][1][0]=1; counts[n][1][1]=1;
-    starts[n][2][0]=2; starts[n][2][1]=3; counts[n][2][0]=1; counts[n][2][1]=3;
-    starts[n][3][0]=3; starts[n][3][1]=7; counts[n][3][0]=1; counts[n][3][1]=3;
+    num_segs[n] = 10; /* number of segments for this request */
+    starts[n][0][0]=0; starts[n][0][1]=0; counts[n][0][0]=1; counts[n][0][1]=1;
+    starts[n][1][0]=1; starts[n][1][1]=0; counts[n][1][0]=1; counts[n][1][1]=1;
+    starts[n][2][0]=2; starts[n][2][1]=0; counts[n][2][0]=1; counts[n][2][1]=1;
+    starts[n][3][0]=3; starts[n][3][1]=2; counts[n][3][0]=1; counts[n][3][1]=1;
+    starts[n][4][0]=4; starts[n][4][1]=1; counts[n][4][0]=1; counts[n][4][1]=2;
+    starts[n][5][0]=5; starts[n][5][1]=2; counts[n][5][0]=1; counts[n][5][1]=1;
+    starts[n][6][0]=7; starts[n][6][1]=3; counts[n][6][0]=1; counts[n][6][1]=1;
+    starts[n][7][0]=8; starts[n][7][1]=3; counts[n][7][0]=1; counts[n][7][1]=1;
+    starts[n][8][0]=9; starts[n][8][1]=3; counts[n][8][0]=1; counts[n][8][1]=1;
      /*starts[n][][] counts[n][][] indicate the following pattern.
-              X  X  X  -  -  -  -  -  -  - 
-              -  -  -  -  X  -  -  -  -  - 
-              -  -  -  X  X  X  -  -  -  - 
-              -  -  -  -  -  -  -  X  X  X 
+              X  _  _  _
+              X  _  _  _
+              X  _  _  _
+              _  _  X  _
+              _  X  X  _
+              _  _  X  _
+              _  _  _  _
+              _  _  _  X
+              _  _  _  X
+              _  _  _  X
      */
 
     /* only rank 0, 1, 2, and 3 do I/O:
@@ -266,6 +336,9 @@ int main(int argc, char** argv)
     nreqs = 4;
     if (rank >= 4) nreqs = 0;
 
+    /* bufsize must be max of data type converted before and after */
+    MPI_Offset bufsize = 0;
+
     /* calculate length of each varn request, number of segments in each
      * varn request, and allocate write buffer */
     for (i=0; i<nreqs; i++) {
@@ -281,49 +354,40 @@ int main(int argc, char** argv)
         /* allocate I/O buffer and initialize its contents */
         buffer[i] = (long long*) malloc(req_lens[i] * sizeof(long long));
         for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank;
-    }
 
-    /* write using varn API */
-    for (i=0; i<nreqs; i++) {
-        err = ncmpi_iput_varn_longlong(ncid, varid[i], num_segs[i], starts[i],
-                                       counts[i], buffer[i], &reqs[i]);
-        ERR
+        bufsize += req_lens[i];
     }
-    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
-    ERRS(nreqs, sts)
+    bufsize *= sizeof(long long);
+    if (verbose) printf("%d: Attach buffer size %lld\n", rank, bufsize);
 
-    /* check file contents */
-    if (nprocs >= 4) check_contents(ncid, varid);
+    /* give PnetCDF a space to buffer the nonblocking requests */
+    if (bufsize > 0) {
+        err = ncmpi_buffer_attach(ncid, bufsize); ERR
+    }
 
-    /* read using get_varn API and check contents */
+    /* write using varn API */
     for (i=0; i<nreqs; i++) {
-        for (j=0; j<req_lens[i]; j++) buffer[i][j] = -1;
-        err = ncmpi_iget_varn_longlong(ncid, varid[i], num_segs[i], starts[i],
+        err = ncmpi_bput_varn_longlong(ncid, varid[i], num_segs[i], starts[i],
                                        counts[i], buffer[i], &reqs[i]);
         ERR
     }
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
-    /* check buffer contents */
-    for (i=0; i<nreqs; i++) {
-        for (j=0; j<req_lens[i]; j++)
-            if (buffer[i][j] != rank)
-                printf("Expected read buf[%d][%d]=%d, but got %lld\n",
-                       i,j,rank,buffer[i][j]);
-    }                
+    /* check file contents */
+    if (nprocs >= 4) nerrs += check_contents(ncid, varid);
 
     for (i=0; i<nreqs; i++) free(buffer[i]);
 
     /* test flexible put API, using a noncontiguous buftype */
     for (i=0; i<nreqs; i++) {
         MPI_Datatype buftype;
-        MPI_Type_vector(req_lens[i], 1, 2, MPI_LONG_LONG, &buftype);
+        MPI_Type_vector(req_lens[i], 1, 2, MPI_UNSIGNED, &buftype);
         MPI_Type_commit(&buftype);
         buffer[i] = (long long*) malloc(req_lens[i] * 2 * sizeof(long long));
         for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
 
-        err = ncmpi_iput_varn(ncid, varid[i], num_segs[i], starts[i],
+        err = ncmpi_bput_varn(ncid, varid[i], num_segs[i], starts[i],
                               counts[i], buffer[i], 1, buftype, &reqs[i]);
         ERR
         MPI_Type_free(&buftype);
@@ -332,29 +396,12 @@ int main(int argc, char** argv)
     ERRS(nreqs, sts)
 
     /* check file contents */
-    if (nprocs >= 4) check_contents(ncid, varid);
+    if (nprocs >= 4) nerrs += check_contents(ncid, varid);
 
-    /* test flexible get API, using a noncontiguous buftype */
-    for (i=0; i<nreqs; i++) {
-        MPI_Datatype buftype;
-        MPI_Type_vector(req_lens[i], 1, 2, MPI_LONG_LONG, &buftype);
-        MPI_Type_commit(&buftype);
-        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = -1;
-        err = ncmpi_iget_varn(ncid, varid[i], num_segs[i], starts[i],
-                              counts[i], buffer[i], 1, buftype, &reqs[i]);
-        ERR
-        MPI_Type_free(&buftype);
+    /* free the buffer space for bput */
+    if (bufsize > 0) {
+        err = ncmpi_buffer_detach(ncid); ERR
     }
-    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
-    ERRS(nreqs, sts)
-
-    /* check buffer contents */
-    for (i=0; i<nreqs; i++) {
-        for (j=0; j<req_lens[i]; j++)
-            if (buffer[i][j*2] != rank)
-                printf("Expected read buf[%d][%d]=%d, but got %lld\n",
-                       i,j*2,rank,buffer[i][j*2]);
-    }                
 
     err = ncmpi_close(ncid);
     ERR
@@ -374,6 +421,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/bput_varn_uint.c b/examples/C/bput_varn_uint.c
index c12a81a..d801291 100644
--- a/examples/C/bput_varn_uint.c
+++ b/examples/C/bput_varn_uint.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: bput_varn_uint.c 2325 2016-02-28 07:49:13Z wkliao $ */
+/* $Id: bput_varn_uint.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example tests nonblocking buffered write varn APIs, including
@@ -63,14 +63,15 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 4
 #define NX 10
 #define NDIMS 2
 
-#define ERR \
-    if (err != NC_NOERR) { \
-        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
-    }
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 #define ERRS(n,a) { \
     int _i; \
@@ -78,6 +79,7 @@
         if ((a)[_i] != NC_NOERR) { \
             printf("Error at line=%d: err[%d] %s\n", __LINE__, _i, \
                    ncmpi_strerror((a)[_i])); \
+                   nerrs++; \
         } \
     } \
 }
@@ -114,9 +116,9 @@ usage(char *argv0)
     fprintf(stderr, help, argv0);
 }
 
-static void check_contents(int ncid, int *varid)
+static int check_contents(int ncid, int *varid)
 {
-    int i, j, err;
+    int i, j, err, nerrs=0;
     unsigned int expected[4][NY*NX] = {{1, 1, 1, 3, 3, 0, 0, 2, 3, 3,
                                         0, 2, 2, 2, 1, 3, 3, 2, 2, 2,
                                         3, 3, 2, 1, 1, 1, 0, 0, 3, 3,
@@ -143,18 +145,21 @@ static void check_contents(int ncid, int *varid)
 
         /* check if the contents of buf are expected */
         for (j=0; j<NY*NX; j++)
-            if (r_buffer[j] != expected[i][j])
+            if (r_buffer[j] != expected[i][j]) {
                 printf("Expected file contents [%d][%d]=%u, but got %u\n",
                        i,j,expected[i][j],r_buffer[j]);
+                nerrs++;
+            }
     }
     free(r_buffer);
+    return nerrs;
 }
 
 int main(int argc, char** argv)
 {
     extern int optind;
-    char *filename="testfile.nc", exec[128];
-    int i, j, k, n, rank, nprocs, verbose=1, err;
+    char *filename="testfile.nc", exec[256];
+    int i, j, k, n, rank, nprocs, verbose=1, err, nerrs=0;
     int ncid, cmode, varid[4], dimid[2], nreqs, reqs[4], sts[4];
     unsigned int *buffer[4];
     int num_segs[4], req_lens[4];
@@ -183,7 +188,7 @@ int main(int argc, char** argv)
     if (nprocs != 4 && rank == 0 && verbose)
         printf("Warning: %s is intended to run on 4 processes\n",exec);
 
-    /* set an MPI-IO hint to disable file offset alignment for fix-sized
+    /* set an MPI-IO hint to disable file offset alignment for fixed-size
      * variables */
     MPI_Info_create(&info);
     MPI_Info_set(info, "nc_var_align_size", "1");
@@ -350,6 +355,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/collective_write.c b/examples/C/collective_write.c
index 86b13df..4cf603b 100644
--- a/examples/C/collective_write.c
+++ b/examples/C/collective_write.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: collective_write.c 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: collective_write.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /*
  *    This example mimics the coll_perf.c from ROMIO.
@@ -40,13 +40,19 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NDIMS    3
 #define NUM_VARS 10
 
 #define HANDLE_ERROR {                                \
-    if (err != NC_NOERR)                              \
+    if (err != NC_NOERR) {                            \
         printf("Error at line %d (%s)\n", __LINE__,   \
                ncmpi_strerror(err));                  \
+        nerrs++;                                      \
+    }                                                 \
 }
 
 static void
@@ -90,7 +96,7 @@ int main(int argc, char **argv)
 {
     extern int optind;
     char *filename="testfile.nc", str[512];
-    int i, j, rank, nprocs, len, ncid, bufsize, verbose=1, err;
+    int i, j, rank, nprocs, len, ncid, bufsize, verbose=1, err, nerrs=0;
     int *buf[NUM_VARS], psizes[NDIMS], dimids[NDIMS], varids[NUM_VARS];
     double write_timing, max_write_timing, write_bw;
     MPI_Offset gsizes[NDIMS], starts[NDIMS], counts[NDIMS];
@@ -226,6 +232,6 @@ int main(int argc, char **argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/column_wise.c b/examples/C/column_wise.c
index b6dd4ba..97df6c5 100644
--- a/examples/C/column_wise.c
+++ b/examples/C/column_wise.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: column_wise.c 2325 2016-02-28 07:49:13Z wkliao $ */
+/* $Id: column_wise.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example makes a number of nonblocking API calls, each writes a single
@@ -65,10 +65,14 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 10
 #define NX 4
 
-#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -85,7 +89,7 @@ int main(int argc, char** argv)
 {
     extern int optind;
     char *filename = "testfile.nc";
-    int i, j, verbose=1, rank, nprocs, err, myNX, G_NX, myOff, num_reqs;
+    int i, j, verbose=1, rank, nprocs, err, nerrs=0, myNX, G_NX, myOff, num_reqs;
     int ncid, cmode, varid, dimid[2], *reqs, *sts, **buf;
     MPI_Offset start[2], count[2];
     MPI_Info info;
@@ -108,7 +112,7 @@ int main(int argc, char** argv)
     argv += optind;
     if (argc == 1) filename = argv[0]; /* optional argument */
 
-    /* set an MPI-IO hint to disable file offset alignment for fix-sized
+    /* set an MPI-IO hint to disable file offset alignment for fixed-size
      * variables */
     MPI_Info_create(&info);
     MPI_Info_set(info, "nc_var_align_size", "1");
@@ -225,6 +229,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/create_open.c b/examples/C/create_open.c
index 1a133fa..24e9521 100644
--- a/examples/C/create_open.c
+++ b/examples/C/create_open.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: create_open.c 2150 2015-10-10 05:52:57Z wkliao $ */
+/* $Id: create_open.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use ncmpi_create() to create a new file and
@@ -32,7 +32,11 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
-#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -49,7 +53,7 @@ int main(int argc, char** argv)
 {
     extern int optind;
     char *filename="testfile.nc";
-    int i, rank, verbose=1, err;
+    int i, rank, verbose=1, err, nerrs=0;
     int ncid, cmode, omode;
 
     MPI_Init(&argc, &argv);
@@ -100,6 +104,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/depend b/examples/C/depend
index 52b6997..961cd0e 100644
--- a/examples/C/depend
+++ b/examples/C/depend
@@ -17,6 +17,7 @@ transpose.o: transpose.c
 vard_int.o: vard_int.c
 i_varn_int64.o: i_varn_int64.c
 bput_varn_uint.o: bput_varn_uint.c
+bput_varn_int64.o: bput_varn_int64.c
 fill_mode.o: fill_mode.c
 ghost_cell.o: ghost_cell.c
 req_all.o: req_all.c
diff --git a/examples/C/fill_mode.c b/examples/C/fill_mode.c
index fc48375..1630eeb 100644
--- a/examples/C/fill_mode.c
+++ b/examples/C/fill_mode.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: fill_mode.c 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: fill_mode.c 2602 2016-11-08 18:55:02Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use 
@@ -63,11 +63,15 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 3
 #define NX 4
 
 
-#define ERR {if(err!=NC_NOERR)printf("Error at %s line=%d: %s\n",__FILE__,__LINE__, ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -84,7 +88,7 @@ int main(int argc, char** argv)
 {
     extern int optind;
     char filename[256];
-    int i, j, rank, nprocs, verbose=1, err, rec_varid, fix_varid;
+    int i, j, rank, nprocs, verbose=1, err, nerrs=0, rec_varid, fix_varid;
     int ncid, cmode, dimid[2], buf[NY][NX], no_fill, fill_value, old_mode;
     MPI_Offset  global_ny, global_nx;
     MPI_Offset start[2], count[2];
@@ -201,6 +205,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/flexible_api.c b/examples/C/flexible_api.c
index f331dcf..770a09f 100644
--- a/examples/C/flexible_api.c
+++ b/examples/C/flexible_api.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: flexible_api.c 2150 2015-10-10 05:52:57Z wkliao $ */
+/* $Id: flexible_api.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *
@@ -79,11 +79,15 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NZ 5
 #define NY 5
 #define NX 5
 
-#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -100,7 +104,7 @@ int main(int argc, char** argv)
 {
     extern int optind;
     char *filename="testfile.nc";
-    int i, j, rank, nprocs, verbose=1, err, req, status, ghost_len=3;
+    int i, j, rank, nprocs, verbose=1, err, nerrs=0, req, status, ghost_len=3;
     int ncid, cmode, varid0, varid1, dimid[3], *buf_zy;
     int array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
     double *buf_yx;
@@ -267,6 +271,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/get_info.c b/examples/C/get_info.c
index 1a655d3..ba5514b 100644
--- a/examples/C/get_info.c
+++ b/examples/C/get_info.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: get_info.c 1669 2014-05-24 18:28:16Z wkliao $ */
+/* $Id: get_info.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /*
  *    prints all MPI-IO hints used
@@ -43,11 +43,16 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
 
 #define HANDLE_ERROR {                                \
-    if (err != NC_NOERR)                              \
+    if (err != NC_NOERR) {                            \
         printf("Error at line %d (%s)\n", __LINE__,   \
                ncmpi_strerror(err));                  \
+        nerrs++;                                      \
+    }                                                 \
 }
 
 static void
@@ -85,7 +90,7 @@ int main(int argc, char **argv)
 {
     extern int optind;
     char *filename="testfile.nc";
-    int i, rank, ncid, verbose=1, err;
+    int i, rank, ncid, verbose=1, err, nerrs=0;
     MPI_Info info_used;
 
     MPI_Init(&argc,&argv);
@@ -140,6 +145,6 @@ int main(int argc, char **argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/get_vara.c b/examples/C/get_vara.c
index 0260426..4e0e6c3 100644
--- a/examples/C/get_vara.c
+++ b/examples/C/get_vara.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: get_vara.c 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: get_vara.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example is the read counterpart of example put_vara.c. It shows how to
@@ -60,9 +60,14 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define CHECK_ERR { \
     if (err!=NC_NOERR) { \
         printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
+        nerrs++; \
         goto fn_exit; \
     } \
 }
@@ -82,7 +87,7 @@ int main(int argc, char** argv)
 {
     extern int optind;
     char *filename="testfile.nc", str_att[NC_MAX_NAME];
-    int i, rank, nprocs, err, verbose=1, ncid, varid, dimid[2], *buf;
+    int i, rank, nprocs, err, nerrs=0, verbose=1, ncid, varid, dimid[2], *buf;
     float *float_att;
     MPI_Offset len, global_ny, global_nx, local_ny, local_nx;
     MPI_Offset start[2], count[2];
@@ -152,6 +157,7 @@ int main(int argc, char** argv)
     float_att = (float*) malloc(len * sizeof(float));
     err = ncmpi_get_att_float(ncid, varid, "float_att_name", float_att);
     CHECK_ERR
+    free(float_att);
 
     /* the local array size */
     local_ny = global_ny;
@@ -167,6 +173,7 @@ int main(int argc, char** argv)
     /* read a subarray in collective mode */
     err = ncmpi_get_vara_int_all(ncid, varid, start, count, buf);
     CHECK_ERR
+    free(buf);
 
     err = ncmpi_close(ncid);
     CHECK_ERR
@@ -183,6 +190,6 @@ int main(int argc, char** argv)
 
 fn_exit:
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/ghost_cell.c b/examples/C/ghost_cell.c
index 6c1116c..d89a103 100644
--- a/examples/C/ghost_cell.c
+++ b/examples/C/ghost_cell.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: ghost_cell.c 2010 2015-02-14 19:45:48Z wkliao $ */
+/* $Id: ghost_cell.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /*
  * This example shows how to use varm API to write a 2D array buffer with ghost
@@ -74,11 +74,11 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
-#define HANDLE_ERROR {                                         \
-    if (err != NC_NOERR)                                       \
-        printf("Error at %s line %d (%s)\n",__FILE__,__LINE__, \
-               ncmpi_strerror(err));                           \
-}
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -98,7 +98,7 @@ int main(int argc, char **argv)
 {
     extern int optind;
     char *filename="testfile.nc";
-    int i, j, rank, nprocs, len, ncid, bufsize, verbose=1, err;
+    int i, j, rank, nprocs, len, ncid, bufsize, verbose=1, err, nerrs=0;
     int psizes[2], local_rank[2], dimids[2], varid, nghosts;
     int *buf, *buf_ptr;
     MPI_Offset gsizes[2], starts[2], counts[2], imap[2];
@@ -170,18 +170,14 @@ int main(int argc, char **argv)
     }
 
     /* define dimensions */
-    err = ncmpi_def_dim(ncid, "Y", gsizes[0], &dimids[0]);
-    HANDLE_ERROR
-    err = ncmpi_def_dim(ncid, "X", gsizes[1], &dimids[1]);
-    HANDLE_ERROR
+    err = ncmpi_def_dim(ncid, "Y", gsizes[0], &dimids[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", gsizes[1], &dimids[1]); ERR
 
     /* define variable */
-    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimids, &varid);
-    HANDLE_ERROR
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimids, &varid); ERR
 
     /* exit the define mode */
-    err = ncmpi_enddef(ncid);
-    HANDLE_ERROR
+    err = ncmpi_enddef(ncid); ERR
 
     /* set up imap[] for excluding ghost cells */
     imap[1] = 1;
@@ -191,16 +187,14 @@ int main(int argc, char **argv)
     buf_ptr = buf + nghosts * (counts[1]+2*nghosts + 1);
 
     /* write the whole variable in file */
-    err = ncmpi_put_varm_int_all(ncid, varid, starts, counts, NULL, imap, buf_ptr);
-    HANDLE_ERROR
+    err = ncmpi_put_varm_int_all(ncid, varid, starts, counts, NULL, imap, buf_ptr); ERR
 
     /* close the file */
-    err = ncmpi_close(ncid);
-    HANDLE_ERROR
+    err = ncmpi_close(ncid); ERR
 
     free(buf);
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/global_attributes.c b/examples/C/global_attributes.c
index 180d6e5..b09bf4a 100644
--- a/examples/C/global_attributes.c
+++ b/examples/C/global_attributes.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: global_attributes.c 1713 2014-07-06 04:23:57Z wkliao $ */
+/* $Id: global_attributes.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example creates a new file and add 2 global attributes, one is of text
@@ -39,9 +39,14 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define ERR { \
     if(err!=NC_NOERR) { \
         printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
+        nerrs++; \
         goto fn_exit; \
     } \
 }
@@ -62,7 +67,7 @@ int main(int argc, char** argv)
     extern int optind;
     char *filename="testfile.nc";
     char str_att[128], att_name[NC_MAX_NAME];
-    int i, rank, err, verbose=0, ncid, cmode, omode, ngatts;
+    int i, rank, err, nerrs=0, verbose=0, ncid, cmode, omode, ngatts;
     short short_att[10], digit[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
     time_t ltime;
 
@@ -129,7 +134,7 @@ int main(int argc, char** argv)
         err = -1;
     }
     MPI_Allreduce(MPI_IN_PLACE, &err, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
-    if (err < 0) goto fn_exit;
+    if (err < 0) { nerrs++; goto fn_exit; }
 
     /* find the name of first global attribute */
     err = ncmpi_inq_attname(ncid, NC_GLOBAL, 0, att_name);
@@ -142,7 +147,7 @@ int main(int argc, char** argv)
         err = -1;
     }
     MPI_Allreduce(MPI_IN_PLACE, &err, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
-    if (err < 0) goto fn_exit;
+    if (err < 0) { nerrs++; goto fn_exit; }
 
     /* read attribute value */
     err = ncmpi_get_att_text(ncid, NC_GLOBAL, att_name, &str_att[0]);
@@ -159,7 +164,7 @@ int main(int argc, char** argv)
         err = -1;
     }
     MPI_Allreduce(MPI_IN_PLACE, &err, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
-    if (err < 0) goto fn_exit;
+    if (err < 0) { nerrs++; goto fn_exit; }
 
     /* read attribute value */
     err = ncmpi_get_att_short(ncid, NC_GLOBAL, att_name, &short_att[0]);
@@ -181,6 +186,6 @@ int main(int argc, char** argv)
 
 fn_exit:
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/hints.c b/examples/C/hints.c
index b6c1d29..0d36fc9 100644
--- a/examples/C/hints.c
+++ b/examples/C/hints.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: hints.c 1669 2014-05-24 18:28:16Z wkliao $ */
+/* $Id: hints.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example sets two PnetCDF hints:
@@ -36,11 +36,15 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NZ 5
 #define NY 5
 #define NX 5
 
-#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -54,12 +58,12 @@ usage(char *argv0)
 }
 
 static
-void print_hints(int ncid,
-                 int varid0,
-                 int varid1)
+int print_hints(int ncid,
+                int varid0,
+                int varid1)
 {
     char value[MPI_MAX_INFO_VAL];
-    int err, len, flag;
+    int err, len, flag, nerrs=0;
     MPI_Offset header_size, header_extent, var_zy_start, var_yx_start;
     MPI_Offset h_align=-1, v_align=-1, h_chunk=-1;
     MPI_Info info_used;
@@ -105,13 +109,14 @@ void print_hints(int ncid,
     printf("header extent                    = %lld\n", header_extent);
     printf("var_zy start file offset         = %lld\n", var_zy_start);
     printf("var_yx start file offset         = %lld\n", var_yx_start);
+    return nerrs;
 }
 
 int main(int argc, char** argv)
 {
     extern int optind;
     char *filename="testfile.nc";
-    int i, rank, nprocs, verbose=1, err;
+    int i, rank, nprocs, verbose=1, err, nerrs=0;
     int ncid, cmode, varid0, varid1, dimid[3], *buf_zy;
     float *buf_yx;
     MPI_Offset start[2], count[2];
@@ -173,7 +178,7 @@ int main(int argc, char** argv)
     count[0] = NY * nprocs; count[1] = NX;
     err = ncmpi_put_vara_float_all(ncid, varid1, start, count, buf_yx); ERR
 
-    if (rank == 0 && verbose) print_hints(ncid, varid0, varid1);
+    if (rank == 0 && verbose) nerrs += print_hints(ncid, varid0, varid1);
 
     err = ncmpi_close(ncid); ERR
 
@@ -191,6 +196,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/i_varn_int64.c b/examples/C/i_varn_int64.c
index 5f735b6..964edff 100644
--- a/examples/C/i_varn_int64.c
+++ b/examples/C/i_varn_int64.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: i_varn_int64.c 2325 2016-02-28 07:49:13Z wkliao $ */
+/* $Id: i_varn_int64.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example tests nonblocking varn APIs, including
@@ -64,14 +64,15 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 4
 #define NX 10
 #define NDIMS 2
 
-#define ERR \
-    if (err != NC_NOERR) { \
-        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
-    }
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 #define ERRS(n,a) { \
     int _i; \
@@ -79,6 +80,7 @@
         if ((a)[_i] != NC_NOERR) { \
             printf("Error at line=%d: err[%d] %s\n", __LINE__, _i, \
                    ncmpi_strerror((a)[_i])); \
+            nerrs++; \
         } \
     } \
 }
@@ -115,9 +117,9 @@ usage(char *argv0)
     fprintf(stderr, help, argv0);
 }
 
-static void check_contents(int ncid, int *varid)
+static int check_contents(int ncid, int *varid)
 {
-    int i, j, err;
+    int i, j, err, nerrs=0;
     long long expected[4][NY*NX] = {{1, 1, 1, 3, 3, 0, 0, 2, 3, 3,
                                      0, 2, 2, 2, 1, 3, 3, 2, 2, 2,
                                      3, 3, 2, 1, 1, 1, 0, 0, 3, 3,
@@ -144,18 +146,21 @@ static void check_contents(int ncid, int *varid)
 
         /* check if the contents of buf are expected */
         for (j=0; j<NY*NX; j++)
-            if (r_buffer[j] != expected[i][j])
+            if (r_buffer[j] != expected[i][j]) {
                 printf("Expected file contents [%d][%d]=%lld, but got %lld\n",
                        i,j,expected[i][j],r_buffer[j]);
+                nerrs++;
+            }
     }
     free(r_buffer);
+    return nerrs;
 }
 
 int main(int argc, char** argv)
 {
     extern int optind;
-    char *filename="testfile.nc", exec[128];
-    int i, j, k, n, rank, nprocs, verbose=1, err;
+    char *filename="testfile.nc", exec[256];
+    int i, j, k, n, rank, nprocs, verbose=1, err, nerrs=0;
     int ncid, cmode, varid[4], dimid[2], nreqs, reqs[4], sts[4];
     long long *buffer[4];
     int num_segs[4], req_lens[4];
@@ -184,7 +189,7 @@ int main(int argc, char** argv)
     if (nprocs != 4 && rank == 0 && verbose)
         printf("Warning: %s is intended to run on 4 processes\n",exec);
 
-    /* set an MPI-IO hint to disable file offset alignment for fix-sized
+    /* set an MPI-IO hint to disable file offset alignment for fixed-size
      * variables */
     MPI_Info_create(&info);
     MPI_Info_set(info, "nc_var_align_size", "1");
@@ -293,7 +298,7 @@ int main(int argc, char** argv)
     ERRS(nreqs, sts)
 
     /* check file contents */
-    if (nprocs >= 4) check_contents(ncid, varid);
+    if (nprocs >= 4) nerrs += check_contents(ncid, varid);
 
     /* read using get_varn API and check contents */
     for (i=0; i<nreqs; i++) {
@@ -332,7 +337,7 @@ int main(int argc, char** argv)
     ERRS(nreqs, sts)
 
     /* check file contents */
-    if (nprocs >= 4) check_contents(ncid, varid);
+    if (nprocs >= 4) nerrs += check_contents(ncid, varid);
 
     /* test flexible get API, using a noncontiguous buftype */
     for (i=0; i<nreqs; i++) {
@@ -374,6 +379,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/mput.c b/examples/C/mput.c
index 611d754..a4eb700 100644
--- a/examples/C/mput.c
+++ b/examples/C/mput.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: mput.c 2325 2016-02-28 07:49:13Z wkliao $ */
+/* $Id: mput.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use a single call of ncmpi_mput_vara_all() to
@@ -49,12 +49,16 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 4
 #define NX 10
 #define NDIMS 2
 
 
-#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -71,9 +75,9 @@ int main(int argc, char** argv)
 {
     extern int optind;
     char *filename="testfile.nc";
-    int i, rank, nprocs, verbose=1, err;
+    int i, rank, nprocs, verbose=1, err, nerrs=0;
     int ncid, cmode, varid, dimid[2], num_reqs, *buffer, **bufs, *nvarids;
-    MPI_Offset w_len, **starts, **counts, *bufcounts;
+    MPI_Offset w_len, **starts=NULL, **counts=NULL, *bufcounts;
     MPI_Datatype *datatypes;
     MPI_Info info;
 
@@ -98,7 +102,7 @@ int main(int argc, char** argv)
     if (nprocs != 4 && rank == 0 && verbose)
         printf("Warning: this program is intended to run on 4 processes\n");
 
-    /* set an MPI-IO hint to disable file offset alignment for fix-sized
+    /* set an MPI-IO hint to disable file offset alignment for fixed-size
      * variables */
     MPI_Info_create(&info);
     MPI_Info_set(info, "nc_var_align_size", "1");
@@ -127,13 +131,15 @@ int main(int argc, char** argv)
     else if (rank == 2) num_reqs = 5;
     else if (rank == 3) num_reqs = 4;
 
-    starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
-    counts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
-    starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
-    counts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
-    for (i=1; i<num_reqs; i++) {
-        starts[i] = starts[i-1] + NDIMS;
-        counts[i] = counts[i-1] + NDIMS;
+    if (num_reqs > 0) {
+        starts    = (MPI_Offset**) malloc(num_reqs*       sizeof(MPI_Offset*));
+        counts    = (MPI_Offset**) malloc(num_reqs*       sizeof(MPI_Offset*));
+        starts[0] = (MPI_Offset*)  calloc(num_reqs*NDIMS, sizeof(MPI_Offset));
+        counts[0] = (MPI_Offset*)  calloc(num_reqs*NDIMS, sizeof(MPI_Offset));
+        for (i=1; i<num_reqs; i++) {
+            starts[i] = starts[i-1] + NDIMS;
+            counts[i] = counts[i-1] + NDIMS;
+        }
     }
 
     /* assign arbitrary starts and counts */
@@ -204,7 +210,7 @@ int main(int argc, char** argv)
 
     /* set the buffer pointers to different offsets to the I/O buffer */
     bufs    = (int**) malloc(num_reqs * sizeof(int*));
-    bufs[0] = buffer;
+    if (num_reqs > 0) bufs[0] = buffer;
     for (i=1; i<num_reqs; i++) bufs[i] = bufs[i-1] + bufcounts[i-1];
 
     err = ncmpi_mput_vara_all(ncid, num_reqs, nvarids, starts, counts,
@@ -219,10 +225,12 @@ int main(int argc, char** argv)
     free(nvarids);
     free(bufcounts);
     free(datatypes);
-    free(starts[0]);
-    free(counts[0]);
-    free(starts);
-    free(counts);
+    if (num_reqs > 0) {
+        free(starts[0]);
+        free(counts[0]);
+        free(starts);
+        free(counts);
+    }
 
     /* check if there is any PnetCDF internal malloc residue */
     MPI_Offset malloc_size, sum_size;
@@ -235,6 +243,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/nonblocking_write.c b/examples/C/nonblocking_write.c
index f2e46a3..40bd5cd 100644
--- a/examples/C/nonblocking_write.c
+++ b/examples/C/nonblocking_write.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: nonblocking_write.c 2325 2016-02-28 07:49:13Z wkliao $ */
+/* $Id: nonblocking_write.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /*    This example is similar to collective_write.c but using nonblocking APIs.
  *    It creates a netcdf file in CD-5 format and writes a number of
@@ -39,14 +39,14 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NDIMS    3
 #define NUM_VARS 10
 
-#define HANDLE_ERROR {                                \
-    if (err != NC_NOERR)                              \
-        printf("Error at line %d (%s)\n", __LINE__,   \
-               ncmpi_strerror(err));                  \
-}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -88,7 +88,7 @@ void print_info(MPI_Info *info_used)
 int main(int argc, char **argv)
 {
     extern int optind;
-    int i, j, verbose=1, err;
+    int i, j, verbose=1, err, nerrs=0;
     int nprocs, len, *buf[NUM_VARS], bufsize, rank;
     int gsizes[NDIMS], psizes[NDIMS];
     double write_timing, max_write_timing, write_bw;
@@ -143,7 +143,7 @@ int main(int argc, char **argv)
     MPI_Barrier(MPI_COMM_WORLD);
     write_timing = MPI_Wtime();
 
-    /* set an MPI-IO hint to disable file offset alignment for fix-sized
+    /* set an MPI-IO hint to disable file offset alignment for fixed-size
      * variables */
     MPI_Info_create(&info);
     MPI_Info_set(info, "nc_var_align_size", "1");
@@ -163,33 +163,33 @@ int main(int argc, char **argv)
     for (i=0; i<NDIMS; i++) {
         sprintf(str, "%c", 'x'+i);
         err = ncmpi_def_dim(ncid, str, gsizes[i], &dimids[i]);
-        HANDLE_ERROR
+        ERR
     }
 
     /* define variables */
     for (i=0; i<NUM_VARS; i++) {
         sprintf(str, "var%d", i);
         err = ncmpi_def_var(ncid, str, NC_INT, NDIMS, dimids, &varids[i]);
-        HANDLE_ERROR
+        ERR
     }
 
     /* exit the define mode */
     err = ncmpi_enddef(ncid);
-    HANDLE_ERROR
+    ERR
 
     /* get all the hints used */
     err = ncmpi_inq_file_info(ncid, &info_used);
-    HANDLE_ERROR
+    ERR
 
     /* write one variable at a time using iput */
     for (i=0; i<NUM_VARS; i++) {
         err = ncmpi_iput_vara_int(ncid, varids[i], starts, counts, buf[i], &req[i]);
-        HANDLE_ERROR
+        ERR
     }
 
     /* wait for the nonblocking I/O to complete */
     err = ncmpi_wait_all(ncid, NUM_VARS, req, st);
-    HANDLE_ERROR
+    ERR
     for (i=0; i<NUM_VARS; i++) {
         if (st[i] != NC_NOERR)
             printf("Error: nonblocking write fails on request %d (%s)\n",
@@ -201,17 +201,17 @@ int main(int argc, char **argv)
     /* bbufsize must be max of data type converted before and after */
     bbufsize = bufsize * NUM_VARS * sizeof(int);
     err = ncmpi_buffer_attach(ncid, bbufsize);
-    HANDLE_ERROR
+    ERR
 
     for (i=0; i<NUM_VARS; i++) {
         err = ncmpi_bput_vara_int(ncid, varids[i], starts, counts, buf[i], &req[i]);
-        HANDLE_ERROR
+        ERR
         /* can safely change contents or free up the buf[i] here */
     }
 
     /* wait for the nonblocking I/O to complete */
     err = ncmpi_wait_all(ncid, NUM_VARS, req, st);
-    HANDLE_ERROR
+    ERR
     for (i=0; i<NUM_VARS; i++) {
         if (st[i] != NC_NOERR)
             printf("Error: nonblocking write fails on request %d (%s)\n",
@@ -220,30 +220,22 @@ int main(int argc, char **argv)
 
     /* detach the temporary buffer */
     err = ncmpi_buffer_detach(ncid);
-    HANDLE_ERROR
+    ERR
 
     MPI_Offset put_size;
     ncmpi_inq_put_size(ncid, &put_size);
-#ifdef MPI_OFFSET
     MPI_Allreduce(MPI_IN_PLACE, &put_size, 1, MPI_OFFSET, MPI_SUM, MPI_COMM_WORLD);
-#else
-    MPI_Allreduce(MPI_IN_PLACE, &put_size, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD);
-#endif
 
     /* close the file */
     err = ncmpi_close(ncid);
-    HANDLE_ERROR
+    ERR
 
     write_timing = MPI_Wtime() - write_timing;
 
     write_size = bufsize * NUM_VARS * sizeof(int);
     for (i=0; i<NUM_VARS; i++) free(buf[i]);
 
-#ifdef MPI_OFFSET
     MPI_Reduce(&write_size,   &sum_write_size,   1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
-#else
-    MPI_Reduce(&write_size,   &sum_write_size,   1, MPI_LONG_LONG, MPI_SUM, 0, MPI_COMM_WORLD);
-#endif
     MPI_Reduce(&write_timing, &max_write_timing, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
 
     if (rank == 0 && verbose) {
@@ -277,6 +269,6 @@ int main(int argc, char **argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/nonblocking_write_in_def.c b/examples/C/nonblocking_write_in_def.c
index cddd953..8650192 100644
--- a/examples/C/nonblocking_write_in_def.c
+++ b/examples/C/nonblocking_write_in_def.c
@@ -40,14 +40,14 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NDIMS    3
 #define NUM_VARS 10
 
-#define HANDLE_ERROR {                                \
-    if (err != NC_NOERR)                              \
-        printf("Error at line %d (%s)\n", __LINE__,   \
-               ncmpi_strerror(err));                  \
-}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -89,7 +89,7 @@ void print_info(MPI_Info *info_used)
 int main(int argc, char **argv)
 {
     extern int optind;
-    int i, j, verbose=1, err;
+    int i, j, verbose=1, err, nerrs=0;
     int nprocs, len, *buf[NUM_VARS], bufsize, rank;
     int gsizes[NDIMS], psizes[NDIMS];
     double write_timing, max_write_timing, write_bw;
@@ -145,7 +145,7 @@ int main(int argc, char **argv)
     MPI_Barrier(comm);
     write_timing = MPI_Wtime();
 
-    /* set an MPI-IO hint to disable file offset alignment for fix-sized
+    /* set an MPI-IO hint to disable file offset alignment for fixed-size
      * variables */
     MPI_Info_create(&info);
     MPI_Info_set(info, "nc_var_align_size", "1");
@@ -164,14 +164,14 @@ int main(int argc, char **argv)
     for (i=0; i<NDIMS; i++) {
         sprintf(str, "%c", 'x'+i);
         err = ncmpi_def_dim(ncid, str, gsizes[i], &dimids[i]);
-        HANDLE_ERROR
+        ERR
     }
 
     /* define variables */
     for (i=0; i<NUM_VARS; i++) {
         sprintf(str, "var%d", i);
         err = ncmpi_def_var(ncid, str, NC_INT, NDIMS, dimids, &varids[i]);
-        HANDLE_ERROR
+        ERR
     }
 
     /* post a nonblocking request for writing one variable at a time using
@@ -179,7 +179,7 @@ int main(int argc, char **argv)
      * in one ncmpi_wait_all() call */
     for (i=0; i<NUM_VARS; i++) {
         err = ncmpi_iput_vara_int(ncid, varids[i], start, count, buf[i], NULL);
-        HANDLE_ERROR
+        ERR
     }
 
     /* write one variable at a time using bput */
@@ -187,55 +187,47 @@ int main(int argc, char **argv)
     /* bbufsize must be max of data type converted before and after */
     bbufsize = bufsize * NUM_VARS * sizeof(int);
     err = ncmpi_buffer_attach(ncid, bbufsize);
-    HANDLE_ERROR
+    ERR
 
     /* post a nonblocking request for writing one variable at a time using
      * bput and ignore the request ID, as we will flush all pending request
      * in one ncmpi_wait_all() call */
     for (i=0; i<NUM_VARS; i++) {
         err = ncmpi_bput_vara_int(ncid, varids[i], start, count, buf[i], NULL);
-        HANDLE_ERROR
+        ERR
         /* can safely change contents or free up the buf[i] here */
     }
 
     /* exit the define mode */
     err = ncmpi_enddef(ncid);
-    HANDLE_ERROR
+    ERR
 
     /* wait for all the nonblocking I/O to complete */
     err = ncmpi_wait_all(ncid, NC_REQ_ALL, NULL, NULL);
-    HANDLE_ERROR
+    ERR
 
     /* detach the temporary buffer */
     err = ncmpi_buffer_detach(ncid);
-    HANDLE_ERROR
+    ERR
 
     /* get all the hints used */
     err = ncmpi_inq_file_info(ncid, &info_used);
-    HANDLE_ERROR
+    ERR
 
     MPI_Offset put_size;
     ncmpi_inq_put_size(ncid, &put_size);
-#ifdef MPI_OFFSET
     MPI_Allreduce(MPI_IN_PLACE, &put_size, 1, MPI_OFFSET, MPI_SUM, comm);
-#else
-    MPI_Allreduce(MPI_IN_PLACE, &put_size, 1, MPI_LONG_LONG, MPI_SUM, comm);
-#endif
 
     /* close the file */
     err = ncmpi_close(ncid);
-    HANDLE_ERROR
+    ERR
 
     write_timing = MPI_Wtime() - write_timing;
 
     write_size = bufsize * NUM_VARS * sizeof(int);
     for (i=0; i<NUM_VARS; i++) free(buf[i]);
 
-#ifdef MPI_OFFSET
     MPI_Reduce(&write_size, &sum_write_size, 1, MPI_OFFSET, MPI_SUM, 0, comm);
-#else
-    MPI_Reduce(&write_size, &sum_write_size, 1, MPI_LONG_LONG, MPI_SUM, 0, comm);
-#endif
     MPI_Reduce(&write_timing, &max_write_timing, 1, MPI_DOUBLE, MPI_MAX, 0, comm);
 
     if (rank == 0 && verbose) {
@@ -269,6 +261,6 @@ int main(int argc, char **argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/put_vara.c b/examples/C/put_vara.c
index baed78f..f747f57 100644
--- a/examples/C/put_vara.c
+++ b/examples/C/put_vara.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: put_vara.c 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: put_vara.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use ncmpi_put_vara_int_all() to write a 2D
@@ -62,11 +62,15 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 10
 #define NX 4
 
 
-#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -83,7 +87,7 @@ int main(int argc, char** argv)
 {
     extern int optind;
     char filename[256];
-    int i, j, rank, nprocs, verbose=1, err;
+    int i, j, rank, nprocs, verbose=1, err, nerrs=0;
     int ncid, cmode, varid, dimid[2], buf[NY][NX];
     char str_att[128];
     float float_att[100];
@@ -189,6 +193,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/put_varn_float.c b/examples/C/put_varn_float.c
index d269373..4504257 100644
--- a/examples/C/put_varn_float.c
+++ b/examples/C/put_varn_float.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: put_varn_float.c 1669 2014-05-24 18:28:16Z wkliao $ */
+/* $Id: put_varn_float.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use a single call of ncmpi_put_varn_float_all()
@@ -41,11 +41,15 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 4
 #define NX 10
 #define NDIMS 2
 
-#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -62,10 +66,10 @@ int main(int argc, char** argv)
 {
     extern int optind;
     char *filename="testfile.nc";
-    int i, rank, nprocs, verbose=1, err;
+    int i, rank, nprocs, verbose=1, err, nerrs=0;
     int ncid, cmode, varid, dimid[2], num_reqs;
     float *buffer;
-    MPI_Offset **starts;
+    MPI_Offset **starts=NULL;
 
     MPI_Init(&argc, &argv);
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
@@ -110,10 +114,12 @@ int main(int argc, char** argv)
     else if (rank == 2) num_reqs = 9;
     else if (rank == 3) num_reqs = 10;
 
-    starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
-    starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
-    for (i=1; i<num_reqs; i++)
-        starts[i] = starts[i-1] + NDIMS;
+    if (num_reqs > 0) {
+        starts    = (MPI_Offset**) malloc(num_reqs*       sizeof(MPI_Offset*));
+        starts[0] = (MPI_Offset*)  calloc(num_reqs*NDIMS, sizeof(MPI_Offset));
+        for (i=1; i<num_reqs; i++)
+            starts[i] = starts[i-1] + NDIMS;
+    }
 
     /* assign arbitrary starts */
     const int y=0, x=1;
@@ -199,8 +205,10 @@ int main(int argc, char** argv)
     ERR
 
     free(buffer);
-    free(starts[0]);
-    free(starts);
+    if (num_reqs > 0) {
+        free(starts[0]);
+        free(starts);
+    }
 
     /* check if there is any PnetCDF internal malloc residue */
     MPI_Offset malloc_size, sum_size;
@@ -213,6 +221,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/put_varn_int.c b/examples/C/put_varn_int.c
index 1159a11..1db1015 100644
--- a/examples/C/put_varn_int.c
+++ b/examples/C/put_varn_int.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: put_varn_int.c 1669 2014-05-24 18:28:16Z wkliao $ */
+/* $Id: put_varn_int.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use a single call of ncmpi_put_varn_int_all() to
@@ -49,11 +49,15 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 4
 #define NX 10
 #define NDIMS 2
 
-#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -70,9 +74,9 @@ int main(int argc, char** argv)
 {
     extern int optind;
     char *filename="testfile.nc";
-    int i, j, rank, nprocs, verbose=1, err;
+    int i, j, rank, nprocs, verbose=1, err, nerrs=0;
     int ncid, cmode, varid, dimid[2], num_reqs, *buffer;
-    MPI_Offset w_len, **starts, **counts;
+    MPI_Offset w_len, **starts=NULL, **counts=NULL;
 
     MPI_Init(&argc, &argv);
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
@@ -117,13 +121,15 @@ int main(int argc, char** argv)
     else if (rank == 2) num_reqs = 5;
     else if (rank == 3) num_reqs = 4;
 
-    starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
-    counts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
-    starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
-    counts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
-    for (i=1; i<num_reqs; i++) {
-        starts[i] = starts[i-1] + NDIMS;
-        counts[i] = counts[i-1] + NDIMS;
+    if (num_reqs > 0) {
+        starts    = (MPI_Offset**) malloc(num_reqs*       sizeof(MPI_Offset*));
+        counts    = (MPI_Offset**) malloc(num_reqs*       sizeof(MPI_Offset*));
+        starts[0] = (MPI_Offset*)  calloc(num_reqs*NDIMS, sizeof(MPI_Offset));
+        counts[0] = (MPI_Offset*)  calloc(num_reqs*NDIMS, sizeof(MPI_Offset));
+        for (i=1; i<num_reqs; i++) {
+            starts[i] = starts[i-1] + NDIMS;
+            counts[i] = counts[i-1] + NDIMS;
+        }
     }
 
     /* assign arbitrary starts and counts */
@@ -198,10 +204,12 @@ int main(int argc, char** argv)
     ERR
 
     free(buffer);
-    free(starts[0]);
-    free(counts[0]);
-    free(starts);
-    free(counts);
+    if (num_reqs > 0) {
+        free(starts[0]);
+        free(counts[0]);
+        free(starts);
+        free(counts);
+    }
 
     /* check if there is any PnetCDF internal malloc residue */
     MPI_Offset malloc_size, sum_size;
@@ -214,6 +222,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/req_all.c b/examples/C/req_all.c
index 47b55c4..70edc9d 100644
--- a/examples/C/req_all.c
+++ b/examples/C/req_all.c
@@ -57,10 +57,14 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 10
 #define NX 4
 
-#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -77,7 +81,7 @@ int main(int argc, char** argv)
 {
     extern int optind;
     char *filename = "testfile.nc";
-    int i, j, verbose=1, rank, nprocs, err, myNX, G_NX, myOff;
+    int i, j, verbose=1, rank, nprocs, err, nerrs=0, myNX, G_NX, myOff;
     int ncid, cmode, varid, dimid[2], **buf;
     MPI_Offset start[2], count[2];
     MPI_Info info;
@@ -100,7 +104,7 @@ int main(int argc, char** argv)
     argv += optind;
     if (argc == 1) filename = argv[0]; /* optional argument */
 
-    /* set an MPI-IO hint to disable file offset alignment for fix-sized
+    /* set an MPI-IO hint to disable file offset alignment for fixed-size
      * variables */
     MPI_Info_create(&info);
     MPI_Info_set(info, "nc_var_align_size", "1");
@@ -188,6 +192,6 @@ int main(int argc, char** argv)
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/transpose.c b/examples/C/transpose.c
index ee9e1f2..749098e 100644
--- a/examples/C/transpose.c
+++ b/examples/C/transpose.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: transpose.c 2325 2016-02-28 07:49:13Z wkliao $ */
+/* $Id: transpose.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /*
  *    This example shows how to use varm API to write six 3D integer array
@@ -36,13 +36,13 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NDIMS 3
 
-#define HANDLE_ERROR {                                \
-    if (err != NC_NOERR)                              \
-        printf("Error at line %d (%s)\n", __LINE__,   \
-               ncmpi_strerror(err));                  \
-}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -62,7 +62,7 @@ int main(int argc, char **argv)
 {
     extern int optind;
     char *filename="testfile.nc", str[512];
-    int i, j, k, rank, nprocs, len, ncid, bufsize, verbose=1, err;
+    int i, j, k, rank, nprocs, len, ncid, bufsize, verbose=1, err, nerrs=0;
     int *buf, psizes[NDIMS], dimids[NDIMS], dimidsT[NDIMS];
     int XYZ_id, XZY_id, YZX_id, YXZ_id, ZYX_id, ZXY_id;
     MPI_Offset gsizes[NDIMS], starts[NDIMS], counts[NDIMS], imap[NDIMS];
@@ -131,7 +131,7 @@ int main(int argc, char **argv)
                                        + (starts[1]+j)*gsizes[2]
                                        + (starts[2]+i);
 
-    /* set an MPI-IO hint to disable file offset alignment for fix-sized
+    /* set an MPI-IO hint to disable file offset alignment for fixed-size
      * variables */
     MPI_Info_create(&info);
     MPI_Info_set(info, "nc_var_align_size", "1");
@@ -151,45 +151,45 @@ int main(int argc, char **argv)
     for (i=0; i<NDIMS; i++) {
         sprintf(str, "%c", 'Z'-i);
         err = ncmpi_def_dim(ncid, str, gsizes[i], &dimids[i]);
-        HANDLE_ERROR
+        ERR
     }
 
     /* define variable with no transposed file layout: ZYX */
     err = ncmpi_def_var(ncid, "ZYX_var", NC_INT, NDIMS, dimids, &ZYX_id);
-    HANDLE_ERROR
+    ERR
 
     /* define variable with transposed file layout: ZYX -> ZXY */
     dimidsT[0] = dimids[0]; dimidsT[1] = dimids[2]; dimidsT[2] = dimids[1];
     err = ncmpi_def_var(ncid, "ZXY_var", NC_INT, NDIMS, dimidsT, &ZXY_id);
-    HANDLE_ERROR
+    ERR
 
     /* define variable with transposed file layout: ZYX -> YZX */
     dimidsT[0] = dimids[1]; dimidsT[1] = dimids[0]; dimidsT[2] = dimids[2];
     err = ncmpi_def_var(ncid, "YZX_var", NC_INT, NDIMS, dimidsT, &YZX_id);
-    HANDLE_ERROR
+    ERR
 
     /* define variable with transposed file layout: ZYX -> YXZ */
     dimidsT[0] = dimids[1]; dimidsT[1] = dimids[2]; dimidsT[2] = dimids[0];
     err = ncmpi_def_var(ncid, "YXZ_var", NC_INT, NDIMS, dimidsT, &YXZ_id);
-    HANDLE_ERROR
+    ERR
 
     /* define variable with transposed file layout: ZYX -> XZY */
     dimidsT[0] = dimids[2]; dimidsT[1] = dimids[0]; dimidsT[2] = dimids[1];
     err = ncmpi_def_var(ncid, "XZY_var", NC_INT, NDIMS, dimidsT, &XZY_id);
-    HANDLE_ERROR
+    ERR
 
     /* define variable with transposed file layout: ZYX -> XYZ */
     dimidsT[0] = dimids[2]; dimidsT[1] = dimids[1]; dimidsT[2] = dimids[0];
     err = ncmpi_def_var(ncid, "XYZ_var", NC_INT, NDIMS, dimidsT, &XYZ_id);
-    HANDLE_ERROR
+    ERR
 
     /* exit the define mode */
     err = ncmpi_enddef(ncid);
-    HANDLE_ERROR
+    ERR
 
     /* write the whole variable in file: ZYX */
     err = ncmpi_put_vara_int_all(ncid, ZYX_id, starts, counts, buf);
-    HANDLE_ERROR
+    ERR
 
     /* ZYX -> ZXY: */
     imap[1] = 1; imap[2] = counts[2]; imap[0] = counts[1]*counts[2];
@@ -197,7 +197,7 @@ int main(int argc, char **argv)
     countsT[0] = counts[0]; countsT[1] = counts[2]; countsT[2] = counts[1];
     /* write the transposed variable */
     err = ncmpi_put_varm_int_all(ncid, ZXY_id, startsT, countsT, NULL, imap, buf);
-    HANDLE_ERROR
+    ERR
 
     /* ZYX -> YZX: */
     imap[2] = 1; imap[0] = counts[2]; imap[1] = counts[1]*counts[2];
@@ -205,7 +205,7 @@ int main(int argc, char **argv)
     countsT[0] = counts[1]; countsT[1] = counts[0]; countsT[2] = counts[2];
     /* write the transposed variable */
     err = ncmpi_put_varm_int_all(ncid, YZX_id, startsT, countsT, NULL, imap, buf);
-    HANDLE_ERROR
+    ERR
 
     /* ZYX -> YXZ: */
     imap[1] = 1; imap[0] = counts[2]; imap[2] = counts[1]*counts[2];
@@ -213,7 +213,7 @@ int main(int argc, char **argv)
     countsT[0] = counts[1]; countsT[1] = counts[2]; countsT[2] = counts[0];
     /* write the transposed variable */
     err = ncmpi_put_varm_int_all(ncid, YXZ_id, startsT, countsT, NULL, imap, buf);
-    HANDLE_ERROR
+    ERR
 
     /* ZYX -> XZY: */
     imap[0] = 1; imap[2] = counts[2]; imap[1] = counts[1]*counts[2];
@@ -221,7 +221,7 @@ int main(int argc, char **argv)
     countsT[0] = counts[2]; countsT[1] = counts[0]; countsT[2] = counts[1];
     /* write the transposed variable */
     err = ncmpi_put_varm_int_all(ncid, XZY_id, startsT, countsT, NULL, imap, buf);
-    HANDLE_ERROR
+    ERR
 
     /* ZYX -> XYZ: */
     imap[0] = 1; imap[1] = counts[2]; imap[2] = counts[1]*counts[2];
@@ -229,15 +229,15 @@ int main(int argc, char **argv)
     countsT[0] = counts[2]; countsT[1] = counts[1]; countsT[2] = counts[0];
     /* write the transposed variable */
     err = ncmpi_put_varm_int_all(ncid, XYZ_id, startsT, countsT, NULL, imap, buf);
-    HANDLE_ERROR
+    ERR
 
     /* close the file */
     err = ncmpi_close(ncid);
-    HANDLE_ERROR
+    ERR
 
     free(buf);
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
 
diff --git a/examples/C/vard_int.c b/examples/C/vard_int.c
index 486e58c..57e98f7 100644
--- a/examples/C/vard_int.c
+++ b/examples/C/vard_int.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: vard_int.c 2239 2015-12-18 18:21:09Z wkliao $ */
+/* $Id: vard_int.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use the vard API ncmpi_put_vard() and
@@ -49,9 +49,13 @@
 #include <mpi.h>
 #include <pnetcdf.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 2
 #define NX 3
-#define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__,ncmpi_strerror(err));}
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
 
 static void
 usage(char *argv0)
@@ -69,7 +73,7 @@ int main(int argc, char **argv) {
 
     extern int optind;
     char         filename[256];
-    int          i, j, err, ncid, verbose=1, varid0, varid1, dimids[2];
+    int          i, j, err, nerrs=0, ncid, verbose=1, varid0, varid1, dimids[2];
     int          rank, nprocs, array_of_blocklengths[2], buf[NY][NX];
     int          array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
     MPI_Offset   start[2], count[2], recsize, bufcount, len;
@@ -188,5 +192,5 @@ int main(int argc, char **argv) {
     }
 
     MPI_Finalize();
-    return 0;
+    return nerrs;
 }
diff --git a/examples/CXX/block_cyclic.cpp b/examples/CXX/block_cyclic.cpp
index be3dc56..ae989ea 100644
--- a/examples/CXX/block_cyclic.cpp
+++ b/examples/CXX/block_cyclic.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: block_cyclic.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: block_cyclic.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example, generalized from column_wise.cpp, makes a number of nonblocking
@@ -79,6 +79,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 10
 #define NX 4
 
diff --git a/examples/CXX/collective_write.cpp b/examples/CXX/collective_write.cpp
index e2a7b9b..876c08e 100644
--- a/examples/CXX/collective_write.cpp
+++ b/examples/CXX/collective_write.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: collective_write.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: collective_write.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /*
  *    This example mimics the coll_perf.c from ROMIO.
@@ -46,6 +46,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NDIMS    3
 #define NUM_VARS 10
 
diff --git a/examples/CXX/column_wise.cpp b/examples/CXX/column_wise.cpp
index f0a05f5..2128f06 100644
--- a/examples/CXX/column_wise.cpp
+++ b/examples/CXX/column_wise.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: column_wise.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: column_wise.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example makes a number of nonblocking API calls, each writes a single
@@ -72,6 +72,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 10
 #define NX 4
 
diff --git a/examples/CXX/fill_mode.cpp b/examples/CXX/fill_mode.cpp
index 24dd0cd..c1c648f 100644
--- a/examples/CXX/fill_mode.cpp
+++ b/examples/CXX/fill_mode.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: fill_mode.cpp 2012 2015-02-16 05:52:44Z wkliao $ */
+/* $Id: fill_mode.cpp 2602 2016-11-08 18:55:02Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use 
@@ -72,6 +72,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 3
 #define NX 4
 
diff --git a/examples/CXX/flexible_api.cpp b/examples/CXX/flexible_api.cpp
index 12c4987..d637ecf 100644
--- a/examples/CXX/flexible_api.cpp
+++ b/examples/CXX/flexible_api.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: flexible_api.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: flexible_api.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *
@@ -83,6 +83,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NZ 5
 #define NY 5
 #define NX 5
diff --git a/examples/CXX/get_info.cpp b/examples/CXX/get_info.cpp
index 4e96427..e595a72 100644
--- a/examples/CXX/get_info.cpp
+++ b/examples/CXX/get_info.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: get_info.cpp 1839 2014-10-30 20:22:37Z wkliao $ */
+/* $Id: get_info.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /*
  *    prints all MPI-IO hints used
@@ -49,6 +49,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 static void
 usage(char *argv0)
 {
diff --git a/examples/CXX/get_vara.cpp b/examples/CXX/get_vara.cpp
index 0c1ec56..dadbdb7 100644
--- a/examples/CXX/get_vara.cpp
+++ b/examples/CXX/get_vara.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: get_vara.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: get_vara.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example is the read counterpart of example put_vara.cpp. It shows how to
@@ -66,6 +66,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 static void
 usage(char *argv0)
 {
diff --git a/examples/CXX/hints.cpp b/examples/CXX/hints.cpp
index a9eb356..de66529 100644
--- a/examples/CXX/hints.cpp
+++ b/examples/CXX/hints.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: hints.cpp 1839 2014-10-30 20:22:37Z wkliao $ */
+/* $Id: hints.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example sets two PnetCDF hints:
@@ -41,6 +41,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NZ 5
 #define NY 5
 #define NX 5
diff --git a/examples/CXX/nonblocking_write.cpp b/examples/CXX/nonblocking_write.cpp
index fb92bd1..1992ef1 100644
--- a/examples/CXX/nonblocking_write.cpp
+++ b/examples/CXX/nonblocking_write.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: nonblocking_write.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: nonblocking_write.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /*    This example is similar to collective_write.c but using nonblocking APIs.
  *    It creates a netcdf file in CD-5 format and writes a number of
@@ -45,6 +45,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NDIMS    3
 #define NUM_VARS 10
 
@@ -97,7 +101,7 @@ int main(int argc, char **argv)
     MPI_Offset write_size, sum_write_size;
     vector<MPI_Offset> starts(NDIMS), counts(NDIMS);
     MPI_Offset bbufsize, put_size;
-    MPI_Info info_used;
+    MPI_Info info, info_used;
 
     MPI_Init(&argc,&argv);
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
@@ -146,9 +150,13 @@ int main(int argc, char **argv)
     write_timing = MPI_Wtime();
 
     try {
+        MPI_Info_create(&info);
+        MPI_Info_set(info, (char*)"nc_var_align_size", (char*)"1");
+
         /* create the file */
         NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::replace,
-                     NcmpiFile::classic5);
+                     NcmpiFile::classic5, info);
+        MPI_Info_free(&info);
 
         /* define dimensions */
         vector<NcmpiDim> dimids(NDIMS);
diff --git a/examples/CXX/put_vara.cpp b/examples/CXX/put_vara.cpp
index edb65d9..6312ef0 100644
--- a/examples/CXX/put_vara.cpp
+++ b/examples/CXX/put_vara.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: put_vara.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: put_vara.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use NcmpiVar::putVar_all() to write a 2D
@@ -67,6 +67,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 10
 #define NX 4
 
diff --git a/examples/CXX/put_varn_float.cpp b/examples/CXX/put_varn_float.cpp
index 5003878..af6c743 100644
--- a/examples/CXX/put_varn_float.cpp
+++ b/examples/CXX/put_varn_float.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: put_varn_float.cpp 1669 2014-05-24 18:28:16Z wkliao $ */
+/* $Id: put_varn_float.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use a single call of NcmpiVar::putVarn_all()
@@ -46,6 +46,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 4
 #define NX 10
 #define NDIMS 2
@@ -67,7 +71,7 @@ int main(int argc, char** argv)
     char filename[128];
     int i, verbose=1, rank, nprocs, num_reqs;
     float *buffer;
-    MPI_Offset **starts;
+    MPI_Offset **starts=NULL;
 
     MPI_Init(&argc, &argv);
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
@@ -112,10 +116,12 @@ int main(int argc, char** argv)
         else if (rank == 2) num_reqs = 9;
         else if (rank == 3) num_reqs = 10;
 
-        starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
-        starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
-        for (i=1; i<num_reqs; i++)
-            starts[i] = starts[i-1] + NDIMS;
+        if (num_reqs > 0) {
+            starts    = (MPI_Offset**)malloc(num_reqs*       sizeof(MPI_Offset*));
+            starts[0] = (MPI_Offset*) calloc(num_reqs*NDIMS, sizeof(MPI_Offset));
+            for (i=1; i<num_reqs; i++)
+                starts[i] = starts[i-1] + NDIMS;
+        }
 
         /* assign arbitrary starts */
         const int y=0, x=1;
@@ -197,8 +203,10 @@ int main(int argc, char** argv)
         var.putVarn_all(num_reqs, starts, NULL, buffer);
 
         free(buffer);
-        free(starts[0]);
-        free(starts);
+        if (num_reqs > 0) {
+            free(starts[0]);
+            free(starts);
+        }
 
         /* file is close implicitly */
     }
diff --git a/examples/CXX/put_varn_int.cpp b/examples/CXX/put_varn_int.cpp
index 279e71a..23c9ee6 100644
--- a/examples/CXX/put_varn_int.cpp
+++ b/examples/CXX/put_varn_int.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: put_varn_int.cpp 1839 2014-10-30 20:22:37Z wkliao $ */
+/* $Id: put_varn_int.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use a single call of NcmpiVar::putVarn_all() to
@@ -54,6 +54,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 4
 #define NX 10
 #define NDIMS 2
@@ -75,7 +79,7 @@ int main(int argc, char** argv)
     char filename[128];
     int i, j, rank, nprocs, verbose=1;
     int num_reqs, *buffer;
-    MPI_Offset w_len, **starts, **counts;
+    MPI_Offset w_len, **starts=NULL, **counts=NULL;
 
     MPI_Init(&argc, &argv);
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
@@ -120,13 +124,15 @@ int main(int argc, char** argv)
         else if (rank == 2) num_reqs = 5;
         else if (rank == 3) num_reqs = 4;
 
-        starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
-        counts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
-        starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
-        counts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
-        for (i=1; i<num_reqs; i++) {
-            starts[i] = starts[i-1] + NDIMS;
-            counts[i] = counts[i-1] + NDIMS;
+        if (num_reqs > 0) {
+            starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+            counts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+            starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+            counts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+            for (i=1; i<num_reqs; i++) {
+                starts[i] = starts[i-1] + NDIMS;
+                counts[i] = counts[i-1] + NDIMS;
+           }
         }
 
         /* assign arbitrary starts and counts */
@@ -196,10 +202,12 @@ int main(int argc, char** argv)
         var.putVarn_all(num_reqs, starts, counts, buffer);
 
         free(buffer);
-        free(starts[0]);
-        free(counts[0]);
-        free(starts);
-        free(counts);
+        if (num_reqs > 0) {
+            free(starts[0]);
+            free(counts[0]);
+            free(starts);
+            free(counts);
+        }
 
         /* file is close implicitly */
     }
diff --git a/examples/CXX/transpose.cpp b/examples/CXX/transpose.cpp
index 0c6361f..4c820fa 100644
--- a/examples/CXX/transpose.cpp
+++ b/examples/CXX/transpose.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: transpose.cpp 1839 2014-10-30 20:22:37Z wkliao $ */
+/* $Id: transpose.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /*
  *    This example shows how to use varm API to write six 3D integer array
@@ -42,6 +42,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NDIMS 3
 
 #define HANDLE_ERROR {                                \
diff --git a/examples/CXX/vard_int.cpp b/examples/CXX/vard_int.cpp
index d685ee2..b2a94c4 100644
--- a/examples/CXX/vard_int.cpp
+++ b/examples/CXX/vard_int.cpp
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: vard_int.cpp 2239 2015-12-18 18:21:09Z wkliao $ */
+/* $Id: vard_int.cpp 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use the vard API ncmpi_put_vard() and
@@ -55,6 +55,10 @@ using namespace std;
 using namespace PnetCDF;
 using namespace PnetCDF::exceptions;
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #define NY 2
 #define NX 3
 
diff --git a/examples/F77/Makefile.in b/examples/F77/Makefile.in
index b033cab..edd25b0 100644
--- a/examples/F77/Makefile.in
+++ b/examples/F77/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2236 2015-12-18 03:49:41Z wkliao $
+# $Id: Makefile.in 2477 2016-09-06 01:16:50Z wkliao $
 #
 # @configure_input@
 
@@ -14,7 +14,7 @@ include ../../macros.make
 # note the order of -L list matters
 INCLUDES  = -I../../src/lib -I../../src/libf
 ifeq (@SIZEOF_MPI_AINT_IS_4@, yes)
-FPPFLAGS += -DSIZEOF_MPI_AINT_IS_4
+FPPFLAGS += $(FC_DEFINE)SIZEOF_MPI_AINT_IS_4
 endif
 FLDFLAGS := -L../../src/lib $(FLDFLAGS) $(LDFLAGS)
 LIBS     := -lpnetcdf $(LIBS)
diff --git a/examples/F77/block_cyclic.f b/examples/F77/block_cyclic.f
index b912bc5..66e7ed1 100644
--- a/examples/F77/block_cyclic.f
+++ b/examples/F77/block_cyclic.f
@@ -2,7 +2,7 @@
 !  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: block_cyclic.f 2325 2016-02-28 07:49:13Z wkliao $
+! $Id: block_cyclic.f 2522 2016-10-06 00:45:08Z wkliao $
 
 
 ! This example, generalized from column_wise.f, makes a number of nonblocking
@@ -66,13 +66,12 @@
           integer NY, NX
           PARAMETER(NX=10, NY=4)
 
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer i, j, rank, nprocs, err, ierr, num_reqs, get_args
           integer ncid, cmode, varid, dimid(2), stride, block_len
           integer buf(NX, NY)
           integer reqs(NY), sts(NY)
-          integer*8 G_NY, myOff, block_start,
-     +                                  global_nx, global_ny
+          integer*8 G_NY, myOff, block_start, global_nx, global_ny
           integer*8 start(2), count(2)
           integer*8 malloc_size, sum_size
           logical verbose
@@ -96,7 +95,7 @@
           call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
      +                   MPI_COMM_WORLD, err)
 
-          ! set an MPI-IO hint to disable file offset alignment for fix-sized
+          ! set an MPI-IO hint to disable file offset alignment for fixed-size
           ! variables
           call MPI_Info_create(info, err)
           call MPI_Info_set(info, "nc_var_align_size", "1", err)
@@ -277,7 +276,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, 
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/bput_varn_int8.f b/examples/F77/bput_varn_int8.f
index 114b12c..1aee900 100644
--- a/examples/F77/bput_varn_int8.f
+++ b/examples/F77/bput_varn_int8.f
@@ -2,7 +2,7 @@
 !   Copyright (C) 2014, Northwestern University
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: bput_varn_int8.f 2325 2016-02-28 07:49:13Z wkliao $
+! $Id: bput_varn_int8.f 2476 2016-09-06 01:05:33Z wkliao $
 
 ! This example tests nonblocking varn API: nfmpi_bput_varn_int8()
 ! It writes a sequence of requests with arbitrary array indices and
@@ -30,52 +30,28 @@
 !     data:
 !
 !     var0 =
-!      1, 0, 3, 0,
-!      1, 2, 3, 0,
-!      1, 2, 2, 0,
-!      3, 2, 1, 2,
-!      3, 1, 1, 3,
-!      0, 3, 1, 3,
-!      0, 3, 0, 3,
-!      2, 2, 0, 1,
-!      3, 2, 3, 1,
-!      3, 2, 3, 1 ;
+!      1, 1, 1, 3, 3, 0, 0, 2, 3, 3,
+!      0, 2, 2, 2, 1, 3, 3, 2, 2, 2,
+!      3, 3, 2, 1, 1, 1, 0, 0, 3, 3,
+!      0, 0, 0, 2, 3, 3, 3, 1, 1, 1 ;
 !
 !     var1 =
-!      2, 1, 0, 1,
-!      2, 3, 0, 1,
-!      2, 3, 3, 1,
-!      0, 3, 2, 3,
-!      0, 2, 2, 0,
-!      1, 0, 2, 0,
-!      1, 0, 1, 0,
-!      3, 3, 1, 2,
-!      0, 3, 0, 2,
-!      0, 3, 0, 2 ;
+!      2, 2, 2, 0, 0, 1, 1, 3, 0, 0,
+!      1, 3, 3, 3, 2, 0, 0, 3, 3, 3,
+!      0, 0, 3, 2, 2, 2, 1, 1, 0, 0,
+!      1, 1, 1, 3, 0, 0, 0, 2, 2, 2 ;
 !
 !     var2 =
-!      3, 2, 1, 2,
-!      3, 0, 1, 2,
-!      3, 0, 0, 2,
-!      1, 0, 3, 0,
-!      1, 3, 3, 1,
-!      2, 1, 3, 1,
-!      2, 1, 2, 1,
-!      0, 0, 2, 3,
-!      1, 0, 1, 3,
-!      1, 0, 1, 3 ;
+!      3, 3, 3, 1, 1, 2, 2, 0, 1, 1,
+!      2, 0, 0, 0, 3, 1, 1, 0, 0, 0,
+!      1, 1, 0, 3, 3, 3, 2, 2, 1, 1,
+!      2, 2, 2, 0, 1, 1, 1, 3, 3, 3 ;
 !
 !     var3 =
-!      0, 3, 2, 3,
-!      0, 1, 2, 3,
-!      0, 1, 1, 3,
-!      2, 1, 0, 1,
-!      2, 0, 0, 2,
-!      3, 2, 0, 2,
-!      3, 2, 3, 2,
-!      1, 1, 3, 0,
-!      2, 1, 2, 0,
-!      2, 1, 2, 0 ;
+!      0, 0, 0, 2, 2, 3, 3, 1, 2, 2,
+!      3, 1, 1, 1, 0, 2, 2, 1, 1, 1,
+!      2, 2, 1, 0, 0, 0, 3, 3, 2, 2,
+!      3, 3, 3, 1, 2, 2, 2, 0, 0, 0 ;
 !     }
 !
 !    Note the above dump is in C order
@@ -101,9 +77,9 @@
 
           integer NDIMS
           integer*8 NX, NY
-          PARAMETER(NDIMS=2, NX=4, NY=10)
+          PARAMETER(NDIMS=2, NX=10, NY=4)
 
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer i, j, k, n, err, ierr, nprocs, rank, get_args
           integer cmode, ncid, varid(4), dimid(NDIMS), nreqs
           integer reqs(4), sts(4), num_segs(4)
@@ -139,18 +115,18 @@
      +               '4 processes'
 
           ! set an MPI-IO hint to disable file offset alignment for
-          ! fix-sized variables
+          ! fixed-size variables
           call MPI_Info_create(info, err)
           call MPI_Info_set(info, "nc_var_align_size", "1", err)
 
-          call MPI_Info_free(info, err)
-
           ! create file, truncate it if exists
           cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
           err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
      +                       info, ncid)
           call check(err, 'In nfmpi_create: ')
 
+          call MPI_Info_free(info, err)
+
           ! define dimensions x and y
           err = nfmpi_def_dim(ncid, "Y", NY, dimid(2))
           call check(err, 'In nfmpi_def_dim Y: ')
@@ -178,75 +154,88 @@
           ! now we are in data mode
           n = mod(rank, 4) + 1
           num_segs(n) = 4 ! number of segments for this request
-          start(1,1,n)=1
-          start(2,1,n)=6
-          count(1,1,n)=1
-          count(2,1,n)=2
-          start(1,2,n)=2
-          start(2,2,n)=1
+          start(1,1,n)=6
+          start(2,1,n)=1
+          count(1,1,n)=2
+          count(2,1,n)=1
+          start(1,2,n)=1
+          start(2,2,n)=2
           count(1,2,n)=1
           count(2,2,n)=1
-          start(1,3,n)=3
-          start(2,3,n)=7
-          count(1,3,n)=1
-          count(2,3,n)=2
-          start(1,4,n)=4
-          start(2,4,n)=1
-          count(1,4,n)=1
-          count(2,4,n)=3
+          start(1,3,n)=7
+          start(2,3,n)=3
+          count(1,3,n)=2
+          count(2,3,n)=1
+          start(1,4,n)=1
+          start(2,4,n)=4
+          count(1,4,n)=3
+          count(2,4,n)=1
           ! start(:,:,n) n_count(:,:,n) indicate the following:
           ! ("-" means skip)
-          !   -  -  -  -  -  X  X  -  -  -
-          !   X  -  -  -  -  -  -  -  -  -
-          !   -  -  -  -  -  -  X  X  -  -
-          !   X  X  X  -  -  -  -  -  -  -
+          !   _  X  _  X
+          !   _  _  _  X
+          !   _  _  _  X
+          !   _  _  _  _
+          !   _  _  _  _
+          !   X  _  _  _
+          !   X  _  X  _
+          !   _  _  X  _
+          !   _  _  _  _
+          !   _  _  _  _
+
 
           n = mod(rank+1, 4) + 1
           num_segs(n) = 6 ! number of segments for this request
-          start(1,1,n)=1
-          start(2,1,n)=4
-          count(1,1,n)=1
-          count(2,1,n)=2
-          start(1,2,n)=1
-          start(2,2,n)=9
-          count(1,2,n)=1
-          count(2,2,n)=2
-          start(1,3,n)=2
-          start(2,3,n)=6
-          count(1,3,n)=1
-          count(2,3,n)=2
-          start(1,4,n)=3
-          start(2,4,n)=1
-          count(1,4,n)=1
-          count(2,4,n)=2
-          start(1,5,n)=3
-          start(2,5,n)=9
-          count(1,5,n)=1
-          count(2,5,n)=2
-          start(1,6,n)=4
-          start(2,6,n)=5
-          count(1,6,n)=1
-          count(2,6,n)=3
+          start(1,1,n)=4
+          start(2,1,n)=1
+          count(1,1,n)=2
+          count(2,1,n)=1
+          start(1,2,n)=9
+          start(2,2,n)=1
+          count(1,2,n)=2
+          count(2,2,n)=1
+          start(1,3,n)=6
+          start(2,3,n)=2
+          count(1,3,n)=2
+          count(2,3,n)=1
+          start(1,4,n)=1
+          start(2,4,n)=3
+          count(1,4,n)=2
+          count(2,4,n)=1
+          start(1,5,n)=9
+          start(2,5,n)=3
+          count(1,5,n)=2
+          count(2,5,n)=1
+          start(1,6,n)=5
+          start(2,6,n)=4
+          count(1,6,n)=3
+          count(2,6,n)=1
           ! start(:,:,n) n_count(:,:,n) indicate the following:
-          !   -  -  -  X  X  -  -  -  X  X
-          !   -  -  -  -  -  X  X  -  -  -
-          !   X  X  -  -  -  -  -  -  X  X
-          !   -  -  -  -  X  X  X  -  -  -
+          !   _  _  X  _
+          !   _  _  X  _
+          !   _  _  _  _
+          !   X  _  _  _
+          !   X  _  _  X
+          !   _  X  _  X
+          !   _  X  _  X
+          !   _  _  _  _
+          !   X  _  X  _
+          !   X  _  X  _
 
           n = mod(rank+2, 4) + 1
           num_segs(n) = 5 ! number of segments for this request
-          start(1,1,n)=1
-          start(2,1,n)=8
+          start(1,1,n)=8
+          start(2,1,n)=1
           count(1,1,n)=1
           count(2,1,n)=1
           start(1,2,n)=2
           start(2,2,n)=2
-          count(1,2,n)=1
-          count(2,2,n)=3
-          start(1,3,n)=2
-          start(2,3,n)=8
-          count(1,3,n)=1
-          count(2,3,n)=3
+          count(1,2,n)=3
+          count(2,2,n)=1
+          start(1,3,n)=8
+          start(2,3,n)=2
+          count(1,3,n)=3
+          count(2,3,n)=1
           start(1,4,n)=3
           start(2,4,n)=3
           count(1,4,n)=1
@@ -256,34 +245,46 @@
           count(1,5,n)=1
           count(2,5,n)=1
           ! start(:,:,n) n_count(:,:,n) indicate the following:
-          !   -  -  -  -  -  -  -  X  -  -
-          !   -  X  X  X  -  -  -  X  X  X
-          !   -  -  X  -  -  -  -  -  -  -
-          !   -  -  -  X  -  -  -  -  -  -
+          !   _  _  _  _
+          !   _  X  _  _
+          !   _  X  X  _
+          !   _  X  _  X
+          !   _  _  _  _
+          !   _  _  _  _
+          !   _  _  _  _
+          !   X  X  _  _
+          !   _  X  _  _
+          !   _  X  _  _
 
           n = mod(rank+3, 4) + 1
           num_segs(n) = 4 ! number of segments for this request
           start(1,1,n)=1
           start(2,1,n)=1
-          count(1,1,n)=1
-          count(2,1,n)=3
-          start(1,2,n)=2
-          start(2,2,n)=5
+          count(1,1,n)=3
+          count(2,1,n)=1
+          start(1,2,n)=5
+          start(2,2,n)=2
           count(1,2,n)=1
           count(2,2,n)=1
-          start(1,3,n)=3
-          start(2,3,n)=4
-          count(1,3,n)=1
-          count(2,3,n)=3
-          start(1,4,n)=4
-          start(2,4,n)=8
-          count(1,4,n)=1
-          count(2,4,n)=3
+          start(1,3,n)=4
+          start(2,3,n)=3
+          count(1,3,n)=3
+          count(2,3,n)=1
+          start(1,4,n)=8
+          start(2,4,n)=4
+          count(1,4,n)=3
+          count(2,4,n)=1
           ! start(:,:,n) n_count(:,:,n) indicate the following:
-          !   X  X  X  -  -  -  -  -  -  -
-          !   -  -  -  -  X  -  -  -  -  -
-          !   -  -  -  X  X  X  -  -  -  -
-          !   -  -  -  -  -  -  -  X  X  X
+          !   X  _  _  _
+          !   X  _  _  _
+          !   X  _  _  _
+          !   _  _  X  _
+          !   _  X  X  _
+          !   _  _  X  _
+          !   _  _  _  _
+          !   _  _  _  X
+          !   _  _  _  X
+          !   _  _  _  X
 
           ! only rank 0, 1, 2, and 3 do I/O:
           ! each of ranks 0 to 3 write 4 nonblocking requests
@@ -320,6 +321,7 @@
      +                                  buffer(1,i), reqs(i))
              call check(err, 'In nfmpi_bput_varn_int8: ')
           enddo
+
           err = nfmpi_wait_all(ncid, nreqs, reqs, sts)
           call check(err, 'In nfmpi_wait_all: ')
 
@@ -337,7 +339,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8,
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/column_wise.f b/examples/F77/column_wise.f
index ee32861..0bc3533 100644
--- a/examples/F77/column_wise.f
+++ b/examples/F77/column_wise.f
@@ -2,7 +2,7 @@
 !  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: column_wise.f 2325 2016-02-28 07:49:13Z wkliao $
+! $Id: column_wise.f 2476 2016-09-06 01:05:33Z wkliao $
 
 ! This example makes a number of nonblocking API calls, each writes a single
 ! row of a 2D integer array. Each process writes NY rows and any two
@@ -69,7 +69,7 @@
           integer NY, NX
           PARAMETER(NX=10, NY=4)
 
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer i, j, rank, nprocs, err, ierr, num_reqs, get_args
           integer ncid, cmode, varid, dimid(2)
           integer buf(NX, NY)
@@ -99,7 +99,7 @@
      +                   MPI_COMM_WORLD, err)
 
           ! set an MPI-IO hint to disable file offset alignment for
-          ! fix-sized variables
+          ! fixed-size variables
           call MPI_Info_create(info, err)
           call MPI_Info_set(info, "nc_var_align_size", "1", err)
 
@@ -190,7 +190,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, 
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/fill_mode.f b/examples/F77/fill_mode.f
index 3d20c8b..531fe5f 100644
--- a/examples/F77/fill_mode.f
+++ b/examples/F77/fill_mode.f
@@ -2,7 +2,7 @@
 !   Copyright (C) 2015, Northwestern University
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: fill_mode.f 2245 2015-12-20 18:39:52Z wkliao $
+! $Id: fill_mode.f 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example shows how to use
@@ -69,7 +69,7 @@
           include 'mpif.h'
           include 'pnetcdf.inc'
 
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer i, j, err, ierr, nprocs, rank, get_args
           integer cmode, ncid, rec_varid, fix_varid, dimid(2)
           integer no_fill, fill_value, old_mode
@@ -213,7 +213,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, 
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/flexible_api.f b/examples/F77/flexible_api.f
index 55e1e97..cf24180 100644
--- a/examples/F77/flexible_api.f
+++ b/examples/F77/flexible_api.f
@@ -2,7 +2,7 @@
 !   Copyright (C) 2013, Northwestern University
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: flexible_api.f 2325 2016-02-28 07:49:13Z wkliao $
+! $Id: flexible_api.f 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example shows how to use PnetCDF flexible API, nfmpi_put_vara_all()
@@ -70,7 +70,7 @@
           include "mpif.h"
           include "pnetcdf.inc"
 
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer err, ierr, nprocs, rank, i, j, ghost_len, get_args
           integer cmode, ncid, varid, dimid(2)
           integer*8 nx, ny, global_nx, global_ny
@@ -180,7 +180,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, 
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/get_info.f b/examples/F77/get_info.f
index e14ed90..8587723 100644
--- a/examples/F77/get_info.f
+++ b/examples/F77/get_info.f
@@ -3,7 +3,7 @@
 !  Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: get_info.f 2224 2015-12-16 06:10:36Z wkliao $
+! $Id: get_info.f 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 !    To compile:
@@ -83,7 +83,7 @@
  998    format(A,I13,A)
         err = nfmpi_inq_malloc_size(malloc_size)
         if (err .EQ. NF_NOERR) then
-            call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+            call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, 
      +                      MPI_SUM, 0, MPI_COMM_WORLD, err)
             if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +          print 998,
diff --git a/examples/F77/hints.f b/examples/F77/hints.f
index 2f068ef..faca2f5 100644
--- a/examples/F77/hints.f
+++ b/examples/F77/hints.f
@@ -3,7 +3,7 @@
 !  Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: hints.f 2224 2015-12-16 06:10:36Z wkliao $
+! $Id: hints.f 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example sets two PnetCDF hints:
@@ -237,7 +237,7 @@
  998  format(A,I13,A)
       err = nfmpi_inq_malloc_size(malloc_size)
       if (err .EQ. NF_NOERR) then
-          call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+          call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, 
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
       if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +        print 998,
diff --git a/examples/F77/i_varn_real.f b/examples/F77/i_varn_real.f
index b659b9c..4bcea32 100644
--- a/examples/F77/i_varn_real.f
+++ b/examples/F77/i_varn_real.f
@@ -2,7 +2,7 @@
 !   Copyright (C) 2014, Northwestern University
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: i_varn_real.f 2325 2016-02-28 07:49:13Z wkliao $
+! $Id: i_varn_real.f 2476 2016-09-06 01:05:33Z wkliao $
 
 ! This example tests nonblocking varn API, nfmpi_iput_varn_real()
 ! It writes a sequence of requests with arbitrary array indices and
@@ -103,7 +103,7 @@
           integer*8 NX, NY
           PARAMETER(NDIMS=2, NX=4, NY=10)
 
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer i, j, n, err, ierr, nprocs, rank, get_args
           integer cmode, ncid, varid(4), dimid(NDIMS), nreqs
           integer reqs(4), sts(4), num_segs(4)
@@ -139,7 +139,7 @@
      +               '4 processes'
 
           ! set an MPI-IO hint to disable file offset alignment for
-          ! fix-sized variables
+          ! fixed-size variables
           call MPI_Info_create(info, err)
           call MPI_Info_set(info, "nc_var_align_size", "1", err)
 
@@ -316,7 +316,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8,
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/nonblocking_write.f b/examples/F77/nonblocking_write.f
index 47af878..f6eb067 100644
--- a/examples/F77/nonblocking_write.f
+++ b/examples/F77/nonblocking_write.f
@@ -2,7 +2,7 @@
 !  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: nonblocking_write.f 2325 2016-02-28 07:49:13Z wkliao $
+! $Id: nonblocking_write.f 2476 2016-09-06 01:05:33Z wkliao $
 
 !    This example is the Fortran 77 version of nonblocking_write.c
 !    It creates a netcdf file in CD-5 format and writes a number of
@@ -40,7 +40,7 @@
           integer NDIMS, NUM_VARS, BUFSIZE
           PARAMETER(NDIMS=3, NUM_VARS=10, BUFSIZE=1000)
 
-          character*128 filename, cmd, str
+          character*256 filename, cmd, str
           integer i, j, cmode, err, ierr, get_args, info
           integer rank, nprocs, ncid, len
           integer buf(BUFSIZE, NUM_VARS), buf1d(BUFSIZE)
@@ -102,7 +102,7 @@
           enddo
 
           ! set an MPI-IO hint to disable file offset alignment for
-          ! fix-sized variables
+          ! fixed-size variables
           call MPI_Info_create(info, err)
           call MPI_Info_set(info, "nc_var_align_size", "1", err)
 
@@ -196,7 +196,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8,
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/put_vara.f b/examples/F77/put_vara.f
index 0225e49..c849f96 100644
--- a/examples/F77/put_vara.f
+++ b/examples/F77/put_vara.f
@@ -2,7 +2,7 @@
 !   Copyright (C) 2013, Northwestern University
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: put_vara.f 2245 2015-12-20 18:39:52Z wkliao $
+! $Id: put_vara.f 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example shows how to use nfmpi_put_vara_int_all() to write a 2D
@@ -68,7 +68,7 @@
           include 'mpif.h'
           include 'pnetcdf.inc'
 
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer i, j, err, ierr, nprocs, rank, get_args, dummy
           integer cmode, ncid, varid, dimid(2)
           integer*8 nx, ny, global_nx, global_ny
@@ -145,7 +145,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, 
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/put_varn_int.f b/examples/F77/put_varn_int.f
index a9af29d..6ec78a2 100644
--- a/examples/F77/put_varn_int.f
+++ b/examples/F77/put_varn_int.f
@@ -2,7 +2,7 @@
 !   Copyright (C) 2013, Northwestern University
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: put_varn_int.f 2224 2015-12-16 06:10:36Z wkliao $
+! $Id: put_varn_int.f 2476 2016-09-06 01:05:33Z wkliao $
 
 ! This example shows how to use a single call of nfmpi_put_varn_int_all() to
 ! write a sequence of requests with arbitrary array indices and lengths.
@@ -68,7 +68,7 @@
           integer*8 NX, NY
           PARAMETER(NDIMS=2, NX=4, NY=10)
 
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer i, j, err, ierr, nprocs, rank, get_args, dummy
           integer cmode, ncid, varid, dimid(NDIMS), num_reqs
 
@@ -243,7 +243,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, 
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/put_varn_real.f b/examples/F77/put_varn_real.f
index d2dd79f..24db140 100644
--- a/examples/F77/put_varn_real.f
+++ b/examples/F77/put_varn_real.f
@@ -2,7 +2,7 @@
 !  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: put_varn_real.f 2224 2015-12-16 06:10:36Z wkliao $
+! $Id: put_varn_real.f 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example shows how to use a single call of nfmpi_put_varn_real_all()
@@ -53,7 +53,7 @@
           integer NDIMS
           PARAMETER(NDIMS=2)
 
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer rank, nprocs, err, num_reqs, ierr, get_args, dummy
           integer i, j, ncid, cmode, varid, dimid(2), y, x
           real buffer(13)
@@ -246,7 +246,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, 
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/transpose.f b/examples/F77/transpose.f
index 73bd1b8..fc3eca1 100644
--- a/examples/F77/transpose.f
+++ b/examples/F77/transpose.f
@@ -2,7 +2,7 @@
 !   Copyright (C) 2014, Northwestern University
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: transpose.f 2224 2015-12-16 06:10:36Z wkliao $
+! $Id: transpose.f 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 !    This example shows how to use varm API to write six 3D integer
@@ -46,7 +46,7 @@
           include 'mpif.h'
           include 'pnetcdf.inc'
 
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer err, ierr, nprocs, rank, lower_dims, get_args, dummy
           integer cmode, ncid, psizes(3), dimids(3), dimidsT(3)
           integer XYZ_id, XZY_id, YZX_id, YXZ_id, ZYX_id, ZXY_id
@@ -276,7 +276,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, 
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F77/utils.F90 b/examples/F77/utils.F90
index d83aeca..a8318ab 100644
--- a/examples/F77/utils.F90
+++ b/examples/F77/utils.F90
@@ -4,7 +4,7 @@
 !
 !     This is part of the PnetCDF package.
 !
-!     $Id: utils.F90 2120 2015-09-22 07:11:58Z wkliao $
+!     $Id: utils.F90 2346 2016-03-09 01:12:57Z wkliao $
 
     ! This function gets the executable name and output file name from the
     ! command line.
@@ -24,7 +24,7 @@
         integer argc
         character(len=16) quiet_mode, str
 
-
+        get_args = 1
         call getarg(0, cmd)
         argc = IARGC()
         if (argc .GT. max_argc) then
diff --git a/examples/F77/vard_int.F b/examples/F77/vard_int.F
index 814f8f9..890f695 100644
--- a/examples/F77/vard_int.F
+++ b/examples/F77/vard_int.F
@@ -2,7 +2,7 @@
 !   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: vard_int.F 2239 2015-12-18 18:21:09Z wkliao $
+! $Id: vard_int.F 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example shows how to use the vard API nfmpi_put_vard() and
@@ -58,7 +58,7 @@
           implicit none
           include "mpif.h"
           include "pnetcdf.inc"
-          character*128 filename, cmd
+          character*256 filename, cmd
           integer err, ierr, nprocs, rank, i, j, get_args, dummy
           integer cmode, ncid, varid0, varid1, dimid(2)
           integer*8 NX, NY, len, bufcount
@@ -219,7 +219,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8,
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
diff --git a/examples/F90/block_cyclic.f90 b/examples/F90/block_cyclic.f90
index c9dc450..e3a8cb3 100644
--- a/examples/F90/block_cyclic.f90
+++ b/examples/F90/block_cyclic.f90
@@ -2,7 +2,7 @@
 !  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: block_cyclic.f90 2325 2016-02-28 07:49:13Z wkliao $
+! $Id: block_cyclic.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 
 ! This example, generalized from column_wise.f, makes a number of nonblocking
@@ -66,7 +66,7 @@
           integer NY, NX
           PARAMETER(NX=10, NY=4)
 
-          character(LEN=128) filename, cmd
+          character(LEN=256) filename, cmd
           integer i, j, rank, nprocs, err, num_reqs, ierr, get_args, dummy
           integer ncid, cmode, varid, dimid(2), stride, block_len
           integer, dimension(:,:), allocatable :: buf
@@ -95,7 +95,7 @@
           call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
 
           ! set an MPI-IO hint to disable file offset alignment for
-          ! fix-sized variables
+          ! fixed-size variables
           call MPI_Info_create(info, err)
           call MPI_Info_set(info, "nc_var_align_size", "1", err)
 
@@ -273,7 +273,7 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/F90/column_wise.f90 b/examples/F90/column_wise.f90
index ef0b3be..0f89367 100644
--- a/examples/F90/column_wise.f90
+++ b/examples/F90/column_wise.f90
@@ -2,7 +2,7 @@
 !  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: column_wise.f90 2325 2016-02-28 07:49:13Z wkliao $
+! $Id: column_wise.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 ! This example makes a number of nonblocking API calls, each writes a single
 ! row of a 2D integer array. Each process writes NY rows and any two
@@ -69,7 +69,7 @@
           integer NY, NX
           PARAMETER(NX=10, NY=4)
 
-          character(LEN=128) filename, cmd
+          character(LEN=256) filename, cmd
           integer i, rank, nprocs, err, num_reqs, ierr, get_args, dummy
           integer ncid, cmode, varid, dimid(2)
           integer buf(NX, NY)
@@ -98,7 +98,7 @@
           call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
 
           ! set an MPI-IO hint to disable file offset alignment for
-          ! fix-sized variables
+          ! fixed-size variables
           call MPI_Info_create(info, err)
           call MPI_Info_set(info, "nc_var_align_size", "1", err)
 
@@ -181,7 +181,7 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/F90/fill_mode.f90 b/examples/F90/fill_mode.f90
index f3e2a79..c401d6c 100644
--- a/examples/F90/fill_mode.f90
+++ b/examples/F90/fill_mode.f90
@@ -2,7 +2,7 @@
 !   Copyright (C) 2015, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: fill_mode.f90 2245 2015-12-20 18:39:52Z wkliao $
+! $Id: fill_mode.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 ! This example shows how to use
 ! 1. nf90mpi_set_fill() to enable fill mode
@@ -73,7 +73,7 @@
           use pnetcdf
           implicit none
 
-          character(LEN=128) filename, cmd
+          character(LEN=256) filename, cmd
           integer err, nprocs, rank, ierr, get_args, dummy
           integer cmode, ncid, rec_varid, fix_varid, dimid(2)
           integer no_fill, fill_value, old_mode
@@ -205,7 +205,7 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/F90/flexible_api.f90 b/examples/F90/flexible_api.f90
index aa779c3..5a01049 100644
--- a/examples/F90/flexible_api.f90
+++ b/examples/F90/flexible_api.f90
@@ -2,7 +2,7 @@
 !   Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: flexible_api.f90 2245 2015-12-20 18:39:52Z wkliao $
+! $Id: flexible_api.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example shows how to use PnetCDF flexible API, nf90mpi_put_var_all()
@@ -70,7 +70,7 @@
           use pnetcdf
           implicit none
 
-          character(LEN=128) filename, cmd
+          character(LEN=256) filename, cmd
           integer err, nprocs, rank, i, j, ghost_len, ierr, get_args, dummy
           integer cmode, ncid, varid, dimid(2)
           integer(kind=MPI_OFFSET_KIND) nx, ny, global_nx, global_ny
@@ -169,7 +169,7 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/F90/get_info.f90 b/examples/F90/get_info.f90
index 86c8e9c..e2e1039 100644
--- a/examples/F90/get_info.f90
+++ b/examples/F90/get_info.f90
@@ -5,7 +5,7 @@
 !*  See COPYRIGHT notice in top-level directory.
 !*
 !*********************************************************************/
-! $Id: get_info.f90 2139 2015-10-08 01:59:10Z wkliao $
+! $Id: get_info.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 !    To compile:
 !        mpif90 -O2 get_info.f90 -o get_info -lpnetcdf
@@ -82,7 +82,7 @@
  998    format(A,I13,A)
         err = nf90mpi_inq_malloc_size(malloc_size)
         if (err == NF90_NOERR) then
-            call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+            call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                             MPI_SUM, 0, MPI_COMM_WORLD, err)
             if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                 'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/F90/hints.f90 b/examples/F90/hints.f90
index 05198f4..625cb35 100644
--- a/examples/F90/hints.f90
+++ b/examples/F90/hints.f90
@@ -4,7 +4,7 @@
 !  Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: hints.f90 2139 2015-10-08 01:59:10Z wkliao $
+! $Id: hints.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example sets two PnetCDF hints:
@@ -234,7 +234,7 @@
  998  format(A,I13,A)
       err = nf90mpi_inq_malloc_size(malloc_size)
       if (err == NF90_NOERR) then
-          call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+          call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                           MPI_SUM, 0, MPI_COMM_WORLD, err)
           if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
               'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/F90/nonblocking_write.f90 b/examples/F90/nonblocking_write.f90
index 24b6745..38db943 100644
--- a/examples/F90/nonblocking_write.f90
+++ b/examples/F90/nonblocking_write.f90
@@ -2,7 +2,7 @@
 !  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: nonblocking_write.f90 2325 2016-02-28 07:49:13Z wkliao $
+! $Id: nonblocking_write.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 !    This example is the Fortran 90 version of nonblocking_write.c
 !    It creates a netcdf file in CD-5 format and writes a number of
@@ -101,7 +101,7 @@
           enddo
 
           ! set an MPI-IO hint to disable file offset alignment for
-          ! fix-sized variables
+          ! fixed-size variables
           call MPI_Info_create(info, err)
           call MPI_Info_set(info, "nc_var_align_size", "1", err)
 
@@ -190,7 +190,7 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/F90/put_var.f90 b/examples/F90/put_var.f90
index 957cbd9..0be61b6 100644
--- a/examples/F90/put_var.f90
+++ b/examples/F90/put_var.f90
@@ -2,7 +2,7 @@
 !   Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: put_var.f90 2245 2015-12-20 18:39:52Z wkliao $
+! $Id: put_var.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example shows how to use nf90mpi_put_var_all() to write a 2D
@@ -68,7 +68,7 @@
           use pnetcdf
           implicit none
 
-          character(LEN=128) filename, cmd
+          character(LEN=256) filename, cmd
           integer err, nprocs, rank, ierr, get_args, dummy
           integer cmode, ncid, varid, dimid(2)
           integer(kind=MPI_OFFSET_KIND) nx, ny, global_nx, global_ny
@@ -139,7 +139,7 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/F90/put_varn_int.f90 b/examples/F90/put_varn_int.f90
index 0c15021..3a0a62d 100644
--- a/examples/F90/put_varn_int.f90
+++ b/examples/F90/put_varn_int.f90
@@ -2,7 +2,7 @@
 !   Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: put_varn_int.f90 2139 2015-10-08 01:59:10Z wkliao $
+! $Id: put_varn_int.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 ! This example shows how to use a single call of nf90mpi_put_varn_all() to
 ! write a sequence of requests with arbitrary array indices and lengths.
@@ -68,7 +68,7 @@
           integer(kind=MPI_OFFSET_KIND) NX, NY
           PARAMETER(NDIMS=2, NX=4, NY=10)
 
-          character(LEN=128) filename, cmd
+          character(LEN=256) filename, cmd
           integer i, j, err, nprocs, rank, ierr, get_args, dummy
           integer cmode, ncid, varid, dimid(NDIMS), num_reqs
 
@@ -246,7 +246,7 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/F90/put_varn_real.f90 b/examples/F90/put_varn_real.f90
index 8f0c293..80cd15f 100644
--- a/examples/F90/put_varn_real.f90
+++ b/examples/F90/put_varn_real.f90
@@ -2,7 +2,7 @@
 !  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: put_varn_real.f90 2139 2015-10-08 01:59:10Z wkliao $
+! $Id: put_varn_real.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example shows how to use a single call of nf90mpi_put_varn_all()
@@ -53,7 +53,7 @@
           integer NDIMS
           PARAMETER(NDIMS=2)
 
-          character(LEN=128) filename, cmd
+          character(LEN=256) filename, cmd
           integer rank, nprocs, err, num_reqs, ierr, get_args, dummy
           integer ncid, cmode, varid, dimid(2), y, x
           real buffer(13)
@@ -239,7 +239,7 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/F90/transpose.f90 b/examples/F90/transpose.f90
index 44b4331..c1ec91f 100644
--- a/examples/F90/transpose.f90
+++ b/examples/F90/transpose.f90
@@ -2,7 +2,7 @@
 !   Copyright (C) 2014, Northwestern University
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: transpose.f90 2139 2015-10-08 01:59:10Z wkliao $
+! $Id: transpose.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 !    This example shows how to use varm API to write six 3D integer
@@ -46,7 +46,7 @@
           use pnetcdf
           implicit none
 
-          character(LEN=128) filename, cmd
+          character(LEN=256) filename, cmd
           integer err, nprocs, rank, lower_dims, ierr, get_args, dummy
           integer cmode, ncid, psizes(3), dimids(3), dimidsT(3)
           integer XYZ_id, XZY_id, YZX_id, YXZ_id, ZYX_id, ZXY_id
@@ -222,7 +222,7 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ', &
diff --git a/examples/F90/utils.F90 b/examples/F90/utils.F90
index d83aeca..9b6775c 100644
--- a/examples/F90/utils.F90
+++ b/examples/F90/utils.F90
@@ -4,7 +4,7 @@
 !
 !     This is part of the PnetCDF package.
 !
-!     $Id: utils.F90 2120 2015-09-22 07:11:58Z wkliao $
+!     $Id: utils.F90 2345 2016-03-08 17:18:49Z wkliao $
 
     ! This function gets the executable name and output file name from the
     ! command line.
@@ -24,7 +24,7 @@
         integer argc
         character(len=16) quiet_mode, str
 
-
+        get_args = 1
         call getarg(0, cmd)
         argc = IARGC()
         if (argc .GT. max_argc) then
diff --git a/examples/F90/vard_int.f90 b/examples/F90/vard_int.f90
index 4644d63..8438df8 100644
--- a/examples/F90/vard_int.f90
+++ b/examples/F90/vard_int.f90
@@ -2,7 +2,7 @@
 !   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: vard_int.f90 2239 2015-12-18 18:21:09Z wkliao $
+! $Id: vard_int.f90 2476 2016-09-06 01:05:33Z wkliao $
 
 !
 ! This example shows how to use the vard API nf90mpi_put_vard() and
@@ -59,7 +59,7 @@
           use pnetcdf
           implicit none
 
-          character(LEN=128) filename, cmd
+          character(LEN=256) filename, cmd
           integer err, nprocs, rank, i, j, ierr, get_args, dummy
           integer cmode, ncid, varid0, varid1, dimid(2)
           integer(kind=MPI_OFFSET_KIND) NX, NY
@@ -212,7 +212,7 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
diff --git a/examples/tutorial/pnetcdf-read-flexible.c b/examples/tutorial/pnetcdf-read-flexible.c
index 7a34695..7c9979a 100644
--- a/examples/tutorial/pnetcdf-read-flexible.c
+++ b/examples/tutorial/pnetcdf-read-flexible.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: pnetcdf-read-flexible.c 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: pnetcdf-read-flexible.c 2369 2016-03-22 21:56:02Z wkliao $ */
 
 /* simple demonstration of pnetcdf 
  * knowing nothing about the file, read in the variables. 
@@ -118,6 +118,7 @@ int main(int argc, char **argv) {
 
     ret = ncmpi_close(ncfile);
     if (ret != NC_NOERR) handle_error(ret, __LINE__);
+    free(dim_sizes);
 
     MPI_Finalize();
     return 0;
diff --git a/examples/tutorial/pnetcdf-read-from-master.c b/examples/tutorial/pnetcdf-read-from-master.c
index 397cca6..983504c 100644
--- a/examples/tutorial/pnetcdf-read-from-master.c
+++ b/examples/tutorial/pnetcdf-read-from-master.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: pnetcdf-read-from-master.c 1723 2014-07-06 05:41:41Z wkliao $ */
+/* $Id: pnetcdf-read-from-master.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* simple demonstration of pnetcdf 
  * text attribute on dataset
@@ -41,6 +41,10 @@
 #include <pnetcdf.h>
 #include <stdio.h>
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 static void handle_error(int status, int lineno)
 {
     fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
@@ -149,6 +153,7 @@ int main(int argc, char **argv) {
     if (rank == 0) {
         ret = ncmpi_close(ncfile);
         if (ret != NC_NOERR) handle_error(ret, __LINE__);
+        free(dim_sizes);
     }
 
     MPI_Finalize();
diff --git a/examples/tutorial/pnetcdf-read-nfiles.c b/examples/tutorial/pnetcdf-read-nfiles.c
index 5f9442a..3df81dd 100644
--- a/examples/tutorial/pnetcdf-read-nfiles.c
+++ b/examples/tutorial/pnetcdf-read-nfiles.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: pnetcdf-read-nfiles.c 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: pnetcdf-read-nfiles.c 2369 2016-03-22 21:56:02Z wkliao $ */
 
 /* simple demonstration of pnetcdf 
  * text attribute on dataset
@@ -128,6 +128,7 @@ int main(int argc, char **argv) {
 
     ret = ncmpi_close(ncfile);
     if (ret != NC_NOERR) handle_error(ret, __LINE__);
+    free(dim_sizes);
 
     MPI_Finalize();
     return 0;
diff --git a/examples/tutorial/pnetcdf-read-standard.c b/examples/tutorial/pnetcdf-read-standard.c
index 952ddab..691b267 100644
--- a/examples/tutorial/pnetcdf-read-standard.c
+++ b/examples/tutorial/pnetcdf-read-standard.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: pnetcdf-read-standard.c 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: pnetcdf-read-standard.c 2369 2016-03-22 21:56:02Z wkliao $ */
 
 /* simple demonstration of pnetcdf:
  * knowing nothing about the file, read in the variables. 
@@ -117,6 +117,7 @@ int main(int argc, char **argv) {
 
     ret = ncmpi_close(ncfile);
     if (ret != NC_NOERR) handle_error(ret, __LINE__);
+    free(dim_sizes);
 
     MPI_Finalize();
     return 0;
diff --git a/examples/tutorial/pnetcdf-write-nb.c b/examples/tutorial/pnetcdf-write-nb.c
index c0dc3ef..a639213 100644
--- a/examples/tutorial/pnetcdf-write-nb.c
+++ b/examples/tutorial/pnetcdf-write-nb.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: pnetcdf-write-nb.c 2095 2015-09-07 21:15:24Z wkliao $ */
+/* $Id: pnetcdf-write-nb.c 2388 2016-03-31 16:08:41Z wkliao $ */
 
 /* simple demonstration of pnetcdf 
  * text attribute on dataset
@@ -50,10 +50,10 @@ static void handle_error(int status, int lineno)
 int main(int argc, char **argv) {
 
     int ret, ncfile, nprocs, rank, dimid, varid1, varid2, ndims=1;
-    MPI_Offset start, count=1;
     char buf[13] = "Hello World\n";
-    int data1, data2;
-    int requests[2], statuses[2];
+    int data1, data2, requests[2], statuses[2];
+    MPI_Offset start, count=1;
+    MPI_Info info;
 
     MPI_Init(&argc, &argv);
 
@@ -66,10 +66,15 @@ int main(int argc, char **argv) {
         exit(-1);
     }
 
+    MPI_Info_create(&info);
+    MPI_Info_set(info, "nc_var_align_size", "1");
+
     ret = ncmpi_create(MPI_COMM_WORLD, argv[1],
-                       NC_CLOBBER|NC_64BIT_OFFSET, MPI_INFO_NULL, &ncfile);
+                       NC_CLOBBER|NC_64BIT_OFFSET, info, &ncfile);
     if (ret != NC_NOERR) handle_error(ret, __LINE__);
 
+    MPI_Info_free(&info);
+
     ret = ncmpi_def_dim(ncfile, "d1", nprocs, &dimid);
     if (ret != NC_NOERR) handle_error(ret, __LINE__);
 
diff --git a/examples/tutorial/pnetcdf-write-nfiles.c b/examples/tutorial/pnetcdf-write-nfiles.c
index 790cd5f..14e0119 100644
--- a/examples/tutorial/pnetcdf-write-nfiles.c
+++ b/examples/tutorial/pnetcdf-write-nfiles.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: pnetcdf-write-nfiles.c 2245 2015-12-20 18:39:52Z wkliao $ */
+/* $Id: pnetcdf-write-nfiles.c 2458 2016-08-12 01:16:28Z robl $ */
 
 /* simple demonstration of pnetcdf 
  * text attribute on dataset
@@ -15,8 +15,7 @@
 To run on 4 processes for example,
 % mpiexec -l -n 4 pnetcdf-write-nfiles output.nc
 
-There will be 4+1 files created.
-    output.nc
+There will be 4 files created.
     output.nc.0-4.nc
     output.nc.1-4.nc
     output.nc.2-4.nc 
@@ -121,24 +120,6 @@ int main(int argc, char **argv) {
 }
 
 /* The contents of files created by this program are:
-% ncmpidump  output.nc
-netcdf output {
-// file format: CDF-2 (large file)
-dimensions:
-        d1 = 4 ;
-variables:
-        int v1(d1) ;
-        int v2(d1) ;
-
-// global attributes:
-                :string = "Hello World\n",
-    "" ;
-data:
-
- v1 = 0, 1, 2, 3 ;
-
- v2 = 0, 1, 2, 3 ;
-}
 
 % ncmpidump output.nc.0-4.nc
 netcdf output.nc.0-4 {
diff --git a/macros.make.in b/macros.make.in
index 3e0acbd..dfc784d 100644
--- a/macros.make.in
+++ b/macros.make.in
@@ -1,7 +1,14 @@
-# $Id: macros.make.in 2264 2015-12-22 15:42:59Z wkliao $
-
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: macros.make.in 2615 2016-11-13 23:58:41Z wkliao $
+#
+# @configure_input@
+#
 # The purpose of this file is to contain common make(1) macros.
 # It should be processed by every execution of that utility.
+#
 
 @SET_MAKE@
 
@@ -23,7 +30,7 @@ LIBRARY		= @BUILDDIR@/src/lib/libpnetcdf.a
 
 # Useful tools
 M4		= @M4@
-M4FLAGS		= @M4FLAGS@
+M4FLAGS		= @M4FLAGS@ -I at abs_top_srcdir@/scripts -DPNETCDF
 EGREP		= @EGREP@
 
 # AC_PROG_SED and AC_PROG_GREP are only available on autoconf 2.60 and later
@@ -36,11 +43,17 @@ GREP		= grep
 DEFS		= @DEFS@
 FC_DEFINE	= @FC_DEFINE@
 CPP		= @CPP@
-CPPFLAGS	= $(INCLUDES) $(DEFS) @CPPFLAGS@
-CXXCPPFLAGS     = $(INCLUDES) $(DEFS) @CXXCPPFLAGS@
 FPP		= @FPP@
-FPPFLAGS	= $(INCLUDES) @FPPFLAGS@ @NAGf90FPPFLAGS@
 
+ifeq (@PNETCDF_DEBUG@, 1)
+CPPFLAGS	= $(INCLUDES) $(DEFS) @CPPFLAGS@ -DPNETCDF_DEBUG
+CXXCPPFLAGS	= $(INCLUDES) $(DEFS) @CXXCPPFLAGS@ -DPNETCDF_DEBUG
+FPPFLAGS	= $(INCLUDES) @FPPFLAGS@ @NAGf90FPPFLAGS@ @FC_DEFINE at PNETCDF_DEBUG
+else
+CPPFLAGS	= $(INCLUDES) $(DEFS) @CPPFLAGS@
+CXXCPPFLAGS	= $(INCLUDES) $(DEFS) @CXXCPPFLAGS@
+FPPFLAGS	= $(INCLUDES) @FPPFLAGS@ @NAGf90FPPFLAGS@
+endif
 
 # Compilation:
 MPICC		= @MPICC@
@@ -48,7 +61,7 @@ MPICXX		= @MPICXX@
 MPIF77		= @MPIF77@
 MPIF90		= @MPIF90@
 
-SEQ_CC          = @SEQ_CC@
+SEQ_CC		= @SEQ_CC@
 
 # debugging and optimization options for compiling and linking
 CFLAGS		= @CFLAGS@
@@ -87,7 +100,7 @@ FCLIBS		= @FCLIBS@
 F90LIBS		= @F90LIBS@
 FLDFLAGS	= @FLDFLAGS@
 F90LDFLAGS	= @F90LDFLAGS@
-LDFLAGS		= @LDFLAGS@ 
+LDFLAGS		= @LDFLAGS@
 LIBS		= @LIBS@
 
 LINK.c		= $(MPICC)  $(CFLAGS)   -o $@
diff --git a/pnetcdf-config.in b/pnetcdf-config.in
new file mode 100644
index 0000000..0f70e87
--- /dev/null
+++ b/pnetcdf-config.in
@@ -0,0 +1,319 @@
+#! /bin/sh
+#
+# Copyright (C) 2016, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# This forms the basis for the pnetcdf-config utility, which tells you
+# various things about the PnetCDF installation. This code was based on
+# file nc-config.in from netCDF distribution.
+#
+# $Id$
+#
+# @configure_input@
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+libdir="@libdir@"
+includedir="@includedir@"
+
+# Preprocessing:
+FC_DEFINE="@FC_DEFINE@"
+CPP="@CPP@"
+FPP="@FPP@"
+
+if test "x at PNETCDF_DEBUG@" = x1 ; then
+  CPPFLAGS="@CPPFLAGS@ -DPNETCDF_DEBUG"
+  CXXCPPFLAGS="@CXXCPPFLAGS@ -DPNETCDF_DEBUG"
+  FPPFLAGS="@FPPFLAGS@ @NAGf90FPPFLAGS@ @FC_DEFINE at PNETCDF_DEBUG"
+else
+  CPPFLAGS="@CPPFLAGS@"
+  CXXCPPFLAGS="@CXXCPPFLAGS@"
+  FPPFLAGS="@FPPFLAGS@ @NAGf90FPPFLAGS@"
+fi
+
+# Compilation:
+MPICC="@MPICC@"
+MPICXX="@MPICXX@"
+MPIF77="@MPIF77@"
+MPIF90="@MPIF90@"
+
+# debugging and optimization options for compiling and linking
+CFLAGS="@CFLAGS@"
+CXXFLAGS="@CXXFLAGS@"
+F77FLAGS="@F77FLAGS@ @NAG_FCFLAGS@"
+F90FLAGS="@F90FLAGS@ @NAG_FCFLAGS@"
+
+# Linking:
+FLIBS="@FLIBS@"
+FCLIBS="@FCLIBS@"
+F90LIBS="@F90LIBS@"
+FLDFLAGS="@FLDFLAGS@"
+F90LDFLAGS="@F90LDFLAGS@"
+LDFLAGS="@LDFLAGS@ -L${libdir}"
+LIBS="@LIBS@"
+
+version="@PACKAGE_NAME@ @PNETCDF_VERSION@"
+CC=${MPICC}
+F77=${MPIF77}
+F90=${MPIF90}
+CFLAGS="-I${includedir} ${CFLAGS}"
+LIBS="-lpnetcdf ${LIBS}"
+
+has_fortran="@has_fortran@"
+has_cxx="@has_mpicxx@"
+
+usage()
+{
+    cat <<EOF
+Usage: pnetcdf-config [OPTION]
+
+Available values for OPTION include:
+
+  --help               display this help message and exit
+  --all                display all options
+  --cc                 C compiler
+  --cflags             C compiler flags
+  --cppflags           C pre-processor flags
+  --has-c++            whether C++ API is installed
+  --c++                C++ compiler
+  --cxxflags           C++ compiler flags
+  --cxxppflags         C++ pre-processor flags
+  --has-fortran        whether Fortran API is installed
+  --f77                Fortran 77 compiler
+  --f77flags           Fortran 77 compiler flags
+  --fppflags           Fortran pre-processor flags
+  --f90                Fortran 90 compiler
+  --f90flags           Fortran 90 compiler flags
+  --ldflags            Linker options
+  --libs               library linking information for PnetCDF
+  --relax-coord-bound  Whether using a relaxed coordinate boundary check
+  --in-place-swap      Whether using buffer in-place Endianness byte swap
+  --erange-fill        Whether using fill values for NC_ERANGE error
+  --subfiling          Whether subfiling is enabled or disabled
+  --debug              Whether PnetCDF is built with debug mode
+  --prefix             Install prefix
+  --includedir         Include directory
+  --libdir             Library directory
+  --version            Library version
+EOF
+    exit $1
+}
+
+all()
+{
+        echo
+        echo "This $version has been built with the following features: "
+        echo
+        echo "  --cc                -> $MPICC"
+        echo "  --cflags            -> $CFLAGS"
+        echo "  --cppflags          -> $CPPFLAGS"
+        echo "  --ldflags           -> $LDFLAGS"
+        echo "  --libs              -> $LIBS"
+        echo
+        echo "  --has-c++           -> $has_cxx"
+if test "x$has_cxx" = xyes ; then
+        echo "  --cxx               -> $MPICXX"
+        echo "  --cxxflags          -> $CXXFLAGS"
+        echo "  --cxxppflags        -> $CXXCPPFLAGS"
+fi
+        echo
+        echo "  --has-fortran       -> $has_fortran"
+if test "x$has_fortran" = xyes ; then
+        echo "  --f77               -> $MPIF77"
+        echo "  --f77flags          -> $F77FLAGS"
+        echo "  --fppflags          -> $FPPFLAGS"
+#        echo "  --f77libs           -> $FCLIBS"
+        echo
+        echo "  --f90               -> $MPIF90"
+        echo "  --f90flags          -> $F90FLAGS"
+#        echo "  --f90libs           -> $F90LIBS"
+fi
+        echo
+if test "x${enable_erange_fill}" = xno; then
+        echo "  --erange-fill       -> disabled"
+else
+        echo "  --erange-fill       -> enabled"
+fi
+if test "x at ENABLE_SUBFILING@" = xyes; then
+        echo "  --subfiling         -> enabled"
+else
+        echo "  --subfiling         -> disabled"
+fi
+if test "x at RELAX_COORD_BOUND@" = xyes; then
+        echo "  --relax-coord-bound -> enabled"
+else
+        echo "  --relax-coord-bound -> disabled"
+fi
+if test "x at is_bigendian@" = xno  && (test "x at in_place_swap@" = xno) ; then
+        echo "  --in-place-swap     -> disabled"
+else
+        echo "  --in-place-swap     -> enabled"
+fi
+if test "x at PNETCDF_DEBUG@" = xyes; then
+        echo "  --debug             -> enabled"
+else
+        echo "  --debug             -> disabled"
+fi
+        echo
+        echo "  --prefix            -> $prefix"
+        echo "  --includedir        -> $includedir"
+        echo "  --libdir            -> $libdir"
+        echo "  --version           -> $version"
+}
+
+if test $# -eq 0; then
+    usage 1
+fi
+
+while test $# -gt 0; do
+    case "$1" in
+    # this deals with options in the style
+    # --option=value and extracts the value part
+    # [not currently used]
+    -*=*) value=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+    *) value= ;;
+    esac
+
+    case "$1" in
+
+    --help)
+        usage 0
+        ;;
+
+    --all)
+        all
+        ;;
+
+    --cc)
+        echo "$MPICC" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --cflags)
+        echo "$CFLAGS" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --cppflags)
+        echo "$CPPFLAGS" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --prefix)
+       echo "$prefix" | sed -e 's/^[ \t]*//'
+       ;;
+
+    --includedir)
+       echo "$includedir" | sed -e 's/^[ \t]*//'
+       ;;
+
+    --libdir)
+       echo "$libdir" | sed -e 's/^[ \t]*//'
+       ;;
+
+    --ldflags)
+       echo "$LDFLAGS" | sed -e 's/^[ \t]*//'
+       ;;
+
+    --libs)
+       echo "$LIBS" | sed -e 's/^[ \t]*//'
+       ;;
+
+    --version)
+        echo "$version" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --has-c++)
+        echo "$has_cxx" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --cxx)
+        echo "$MPICXX" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --cxxflags)
+        echo "$CXXFLAGS" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --cxxppflags)
+        echo "$CXXCPPFLAGS" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --has-fortran)
+        echo "$has_fortran" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --f77)
+        echo "$MPIF77" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --f77flags)
+        echo "$F77FLAGS" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --fppflags)
+        echo "$FPPFLAGS" | sed -e 's/^[ \t]*//'
+        ;;
+
+#    --f77libs)
+#        echo "$FCLIBS" | sed -e 's/^[ \t]*//'
+#        ;;
+
+    --f90)
+        echo "$MPIF90" | sed -e 's/^[ \t]*//'
+        ;;
+
+    --f90flags)
+        echo "$F90FLAGS" | sed -e 's/^[ \t]*//'
+        ;;
+
+#    --f90libs)
+#        echo "$F90LIBS" | sed -e 's/^[ \t]*//'
+#        ;;
+
+    --relax-coord-bound)
+if test "x at RELAX_COORD_BOUND@" = xyes; then
+        echo "enabled"
+else
+        echo "disabled"
+fi
+        ;;
+
+    --in-place-swap)
+if test "x at is_bigendian@" = xno  && (test "x at in_place_swap@" = xno) ; then
+        echo "disabled"
+else
+        echo "enabled"
+fi
+        ;;
+
+    --erange-fill)
+if test "x${enable_erange_fill}" = xno; then
+        echo "disabled"
+else
+        echo "enabled"
+fi
+        ;;
+
+    --subfiling)
+if test "x at ENABLE_SUBFILING@" = xyes; then
+        echo "enabled"
+else
+        echo "disabled"
+fi
+        ;;
+
+    --debug)
+if test "x at PNETCDF_DEBUG@" = xyes; then
+        echo "enabled"
+else
+        echo "disabled"
+fi
+        ;;
+
+    *)
+        echo "unknown option: $1"
+        usage 1
+        ;;
+    esac
+    shift
+done
+
+exit 0
diff --git a/src/lib/pnetcdf.pc.in b/pnetcdf_pc.in
similarity index 83%
rename from src/lib/pnetcdf.pc.in
rename to pnetcdf_pc.in
index 350548c..697df49 100644
--- a/src/lib/pnetcdf.pc.in
+++ b/pnetcdf_pc.in
@@ -1,3 +1,11 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# @configure_input@
+#
+
+
 # Name: A human-readable name for the library or package. This does not
 #      affect usage of the pkg-config tool, which uses the name of the .pc file.
 # Description: A brief description of the package.
@@ -25,9 +33,14 @@
 #               but not exposed to applications. The same rule as Cflags
 #               applies here.
 
+prefix=INSTALL_PREFIX   # prefix can be changed by "make install prefix=/path"
+exec_prefix=@exec_prefix@
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
 Name: Parallel-NetCDF
 Description: Parallel-NetCDF (pnetcdf) provides parallel access to NetCDF files
 URL: http://cucis.ece.northwestern.edu/projects/PnetCDF/
 Version: @PNETCDF_VERSION@
-Cflags: -I at prefix@/include
-Libs: -L at prefix@/lib -lpnetcdf
+Cflags: -I${includedir}
+Libs: -L${libdir} -lpnetcdf
diff --git a/rules.make b/rules.make
index 6e88e3d..6261fb0 100644
--- a/rules.make
+++ b/rules.make
@@ -1,4 +1,4 @@
-# $Id: rules.make 2285 2015-12-30 20:48:25Z wkliao $
+# $Id: rules.make 2624 2016-11-15 23:10:00Z wkliao $
 
 # The purpose of this file is to contain common make(1) rules.
 # It should be processed by every execution of the that utility.
@@ -50,6 +50,9 @@
 #.F.f:
 #	$(FPP) $(FPPFLAGS) $*.F | grep -v '^#' >$*.f || ($(RM) -f $*.f; exit 1)
 
+.m4.h:
+	$(M4) $(M4FLAGS) $< >$@
+
 .m4.c:
 	$(M4) $(M4FLAGS) $< >$@
 
@@ -176,8 +179,8 @@ clean:		FORCE
 		(cd $$subdir && $(MAKE) $(MFLAGS) clean) ; \
 	    done; \
 	fi
-	@$(RM) -f *.o *.a *.so *.sl *.i *.Z core core.* $(GARBAGE) \
-		  *.gcda *.gcno gmon.out
+	@$(RM) -f *.o *.a *.so *.sl *.i *.Z core core.* vgcore.* $(GARBAGE) \
+		  *.gcda *.gcno *.gcov gmon.out
 
 distclean:	FORCE
 	@if [ -n "$(PACKING_SUBDIRS)" ]; then \
@@ -193,8 +196,8 @@ distclean:	FORCE
 	    done; \
 	fi
 	@$(RM) -rf SunWS_cache
-	@$(RM) -f *.o *.a *.so *.sl *.i *.Z core core.* $(GARBAGE) \
-		  *.gcda *.gcno gmon.out \
+	@$(RM) -f *.o *.a *.so *.sl *.i *.Z core core.* vgcore.* $(GARBAGE) \
+		  *.gcda *.gcno *.gcov gmon.out \
 	          MANIFEST *.log $(DIST_GARBAGE) cscope.out cscope.files
 	@$(RM) -f Makefile
 
@@ -257,4 +260,5 @@ FORCE:
 .PHONY: subdirs $(SUBDIRS) install $(INSTALLDIRS) uninstall $(UNINSTALLDIRS)
 .PHONY: tests check testing $(CHECK_DIRS) $(PTEST_DIRS) verbose_check verbose_testing $(VCHECK_DIRS)
 .PHONY: ptest ptests ptest2 ptest4 ptest6 ptest8 ptest10
+.PHONY: install_PKGCONFIG uninstall_PKGCONFIG install_CONFIG uninstall_CONFIG
 
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index 99fe19e..08e19a1 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 1388 2013-08-30 19:25:21Z wkliao $
+# $Id: Makefile.in 2596 2016-11-02 17:36:50Z wkliao $
 #
 # @configure_input@
 
@@ -16,7 +16,9 @@ GARBAGE      =
 PACKING_LIST = config.guess \
                config.sub \
                install-sh \
-               Makefile.in
+               Makefile.in \
+               foreach.m4 \
+               utils.m4
 
 all:
 
diff --git a/scripts/foreach.m4 b/scripts/foreach.m4
new file mode 100644
index 0000000..9be25b0
--- /dev/null
+++ b/scripts/foreach.m4
@@ -0,0 +1,8 @@
+divert(`-1')
+# foreach(x, (item_1, item_2, ..., item_n), stmt)
+#   parenthesized list, simple version
+define(`foreach', `pushdef(`$1')_foreach($@)popdef(`$1')')
+define(`_arg1', `$1')
+define(`_foreach', `ifelse(`$2', `()', `',
+  `define(`$1', _arg1$2)$3`'$0(`$1', (shift$2), `$3')')')
+divert`'dnl
diff --git a/scripts/utils.m4 b/scripts/utils.m4
new file mode 100644
index 0000000..7bbc8bc
--- /dev/null
+++ b/scripts/utils.m4
@@ -0,0 +1,183 @@
+dnl
+dnl This utilities file contains common m4 macros used by C/Fortran program
+dnl
+dnl
+define(`_CAT', `$1$2')dnl  concatenate two strings
+dnl
+dnl dnl dnl
+dnl
+define(`FUNC2ITYPE', `ifelse(`$1', `text',      `char',
+                             `$1', `schar',     `schar',
+                             `$1', `uchar',     `uchar',
+                             `$1', `short',     `short',
+                             `$1', `ushort',    `ushort',
+                             `$1', `int',       `int',
+                             `$1', `uint',      `uint',
+                             `$1', `long',      `long',
+                             `$1', `float',     `float',
+                             `$1', `double',    `double',
+                             `$1', `longlong',  `long long',
+                             `$1', `ulonglong', `unsigned long long')')dnl
+dnl
+dnl dnl dnl
+dnl
+define(`ITYPE2MPI',  `ifelse(`$1', `text',      `MPI_CHAR',
+                             `$1', `schar',     `MPI_SIGNED_CHAR',
+                             `$1', `uchar',     `MPI_UNSIGNED_CHAR',
+                             `$1', `short',     `MPI_SHORT',
+                             `$1', `ushort',    `MPI_UNSIGNED_SHORT',
+                             `$1', `int',       `MPI_INT',
+                             `$1', `uint',      `MPI_UNSIGNED',
+                             `$1', `long',      `MPI_LONG',
+                             `$1', `float',     `MPI_FLOAT',
+                             `$1', `double',    `MPI_DOUBLE',
+                             `$1', `longlong',  `MPI_LONG_LONG_INT',
+                             `$1', `ulonglong', `MPI_UNSIGNED_LONG_LONG')')dnl
+dnl
+dnl dnl dnl
+dnl
+define(`MPI2ITYPE',  `ifelse(`$1', `MPI_CHAR',               `text',
+                             `$1', `MPI_SIGNED_CHAR',        `schar',
+                             `$1', `MPI_UNSIGNED_CHAR',      `uchar',
+                             `$1', `MPI_SHORT',              `short',
+                             `$1', `MPI_UNSIGNED_SHORT',     `ushort',
+                             `$1', `MPI_INT',                `int',
+                             `$1', `MPI_UNSIGNED',           `uint',
+                             `$1', `MPI_LONG',               `long',
+                             `$1', `MPI_FLOAT',              `float',
+                             `$1', `MPI_DOUBLE',             `double',
+                             `$1', `MPI_LONG_LONG_INT',      `longlong',
+                             `$1', `MPI_UNSIGNED_LONG_LONG', `ulonglong')')dnl
+dnl
+dnl dnl dnl
+dnl
+define(`ITYPE_LIST', `text, schar, uchar, short, ushort, int, uint, long, float, double, longlong, ulonglong')dnl
+dnl
+dnl
+dnl dnl dnl
+dnl
+define(`CDF2_ITYPE_LIST', `text, schar, short, int, long, float, double')dnl
+dnl
+dnl
+define(`CollIndep', `ifelse(`$1', `_all', `COLL_IO', `INDEP_IO')')dnl
+define(`ReadWrite', `ifelse(`$1',  `get', `READ_REQ',
+                            `$1', `iget', `READ_REQ',
+                                          `WRITE_REQ')')dnl
+define(`BufArgs',   `ifelse(`$2', `',
+                            `ifelse($1, `put', `const void *buf,', `void *buf,')
+                             MPI_Offset   bufcount,
+                             MPI_Datatype buftype',
+                            `ifelse($1, `put', `const FUNC2ITYPE($2) *buf',
+                                                     `FUNC2ITYPE($2) *buf')')')
+dnl
+dnl index arguments for APIs of different kinds
+dnl
+define(`ArgKind', `ifelse(
+       `$1', `1', `const MPI_Offset *start,',
+       `$1', `a', `const MPI_Offset *start,
+                   const MPI_Offset *count,',
+       `$1', `s', `const MPI_Offset *start,
+                   const MPI_Offset *count,
+                   const MPI_Offset *stride,',
+       `$1', `m', `const MPI_Offset *start,
+                   const MPI_Offset *count,
+                   const MPI_Offset *stride,
+                   const MPI_Offset *imap,')')dnl
+dnl
+dnl arguments passed to a function for APIs of different kinds
+dnl
+define(`ArgStartCount', `ifelse(
+       `$1', `',  `NULL,  NULL',
+       `$1', `1', `start, NULL',
+                  `start, count')')dnl
+dnl
+define(`ArgStrideMap', `ifelse(
+       `$1', `s', `stride, NULL',
+       `$1', `m', `stride, imap',
+                  `NULL, NULL')')dnl
+dnl
+define(`API_KIND', `ifelse(
+       `$1', `1', `API_VAR1',
+       `$1', `a', `API_VARA',
+       `$1', `s', `API_VARS',
+       `$1', `m', `API_VARM',
+       `$1', `d', `API_VARD',
+       `$1', `n', `API_VARN',
+       `$1', `',  `API_VAR')')dnl
+dnl
+define(`NC_TYPE',`ifelse(
+`$1', `text',      `NC_CHAR',
+`$1', `schar',     `NC_BYTE',
+`$1', `uchar',     `NC_UBYTE',
+`$1', `short',     `NC_SHORT',
+`$1', `ushort',    `NC_USHORT',
+`$1', `int',       `NC_INT',
+`$1', `long',      `NC_LONG',
+`$1', `uint',      `NC_UINT',
+`$1', `float',     `NC_FLOAT',
+`$1', `double',    `NC_DOUBLE',
+`$1', `longlong',  `NC_INT64',
+`$1', `ulonglong', `NC_UINT64')')dnl
+dnl
+define(`NC_FILL_VALUE',`ifelse(
+`$1', `text',      `NC_FILL_CHAR',
+`$1', `schar',     `NC_FILL_BYTE',
+`$1', `uchar',     `NC_FILL_UBYTE',
+`$1', `short',     `NC_FILL_SHORT',
+`$1', `ushort',    `NC_FILL_USHORT',
+`$1', `int',       `NC_FILL_INT',
+`$1', `long',      `NC_FILL_INT',
+`$1', `uint',      `NC_FILL_UINT',
+`$1', `float',     `NC_FILL_FLOAT',
+`$1', `double',    `NC_FILL_DOUBLE',
+`$1', `longlong',  `NC_FILL_INT64',
+`$1', `ulonglong', `NC_FILL_UINT64')')dnl
+dnl
+define(`IFMT',`ifelse(
+`$1', `text',      `%c',
+`$1', `schar',     `%hhd',
+`$1', `uchar',     `%hhu',
+`$1', `short',     `%hd',
+`$1', `ushort',    `%hu',
+`$1', `int',       `%d',
+`$1', `long',      `%ld',
+`$1', `uint',      `%u',
+`$1', `float',     `%g',
+`$1', `double',    `%g',
+`$1', `longlong',  `%lld',
+`$1', `ulonglong', `%llu')')dnl
+dnl
+define(`PUT_VAR',`ifdef(`PNETCDF',`ncmpi_put_var_$1_all',`nc_put_var_$1')')dnl
+dnl
+define(`GET_VAR',`ifdef(`PNETCDF',`ncmpi_get_var_$1_all',`nc_get_var_$1')')dnl
+dnl
+define(`PUT_VAR1',`ifdef(`PNETCDF',`ncmpi_put_var1_$1_all',`nc_put_var1_$1')')dnl
+dnl
+define(`GET_VAR1',`ifdef(`PNETCDF',`ncmpi_get_var1_$1_all',`nc_get_var1_$1')')dnl
+dnl
+define(`PUT_VARA',`ifdef(`PNETCDF',`ncmpi_put_vara_$1_all',`nc_put_vara_$1')')dnl
+dnl
+define(`GET_VARA',`ifdef(`PNETCDF',`ncmpi_get_vara_$1_all',`nc_get_vara_$1')')dnl
+dnl
+define(`PUT_VARS',`ifdef(`PNETCDF',`ncmpi_put_vars_$1_all',`nc_put_vars_$1')')dnl
+dnl
+define(`GET_VARS',`ifdef(`PNETCDF',`ncmpi_get_vars_$1_all',`nc_get_vars_$1')')dnl
+dnl
+define(`PUT_VARM',`ifdef(`PNETCDF',`ncmpi_put_varm_$1_all',`nc_put_varm_$1')')dnl
+dnl
+define(`GET_VARM',`ifdef(`PNETCDF',`ncmpi_get_varm_$1_all',`nc_get_varm_$1')')dnl
+dnl
+define(`XTYPE_MAX',`ifelse(
+`$1', `text',      `127',
+`$1', `schar',     `127',
+`$1', `uchar',     `255',
+`$1', `short',     `32767',
+`$1', `ushort',    `65535U',
+`$1', `int',       `2147483647',
+`$1', `long',      `2147483647',
+`$1', `uint',      `4294967295U',
+`$1', `float',     `3.402823466e+38f',
+`$1', `double',    `1.79769313486230e+308',
+`$1', `longlong',  `9223372036854775807LL',
+`$1', `ulonglong', `18446744073709551615ULL')')dnl
+dnl
diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in
index 770e76c..079e7aa 100644
--- a/src/lib/Makefile.in
+++ b/src/lib/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2340 2016-03-03 19:45:09Z wkliao $
+# $Id: Makefile.in 2614 2016-11-12 19:50:02Z wkliao $
 #
 # @configure_input@
 
@@ -22,7 +22,12 @@ INCLUDES = -I. -I$(srcdir)
 
 LIBRARY  = libpnetcdf.a
 HEADER   = pnetcdf.h
-PKGCONFIG = pnetcdf.pc
+
+ifeq (@enable_erange_fill@, yes)
+M4FLAGS += -DERANGE_FILL
+endif
+
+M4_HEADERS = ncx_h.m4
 
 M4_SRCS   = getput.m4 \
             i_getput.m4 \
@@ -38,7 +43,6 @@ HEADER_SRCS = fbits.h \
               nc.h \
               nctypes.h \
               ncio.h \
-              ncx.h \
               rnd.h \
               ncmpidtype.h \
               macro.h \
@@ -60,7 +64,8 @@ LIB_CSRCS = mpinetcdf.c \
             utf8proc.c \
             vard.c \
             fill.c \
-            util.c
+            util.c \
+            hash_func.c
 
 ifeq (@enable_subfiling@, yes)
 LIB_CSRCS   += subfile.c
@@ -68,12 +73,12 @@ HEADER_SRCS += subfile.h
 endif
 
 PACKING_LIST = $(LIB_CSRCS) \
+               $(M4_HEADERS) \
                $(M4_SRCS) \
                $(HEADER_SRCS) \
                pnetcdf.h.in \
                depend \
                Makefile.in \
-               pnetcdf.pc.in \
                ncconfig.h.in
 
 ifeq (@enable_subfiling@, no)
@@ -82,9 +87,9 @@ endif
 
 LIB_OBJS   = $(LIB_CSRCS:.c=.o) $(M4_SRCS:.m4=.o)
 
-GARBAGE    = $(LIBRARY) $(M4_SRCS:.m4=.c)
+GARBAGE    = $(LIBRARY) $(M4_SRCS:.m4=.c) ncx.h
 
-DIST_GARBAGE = ncconfig.h pnetcdf.h pnetcdf.pc
+DIST_GARBAGE = ncconfig.h pnetcdf.h
 
 all: $(LIBRARY)
 
@@ -97,11 +102,8 @@ install: $(LIBRARY)
 	$(INSTALL_DATA) $(LIBRARY) $(LIBDIR)/$(LIBRARY)
 	$(INSTALL) -d -m 755 $(INCDIR)
 	$(INSTALL_DATA) $(HEADER) $(INCDIR)/$(HEADER)
-	$(INSTALL) -d -m 755 $(LIBDIR)/pkgconfig
-	$(INSTALL_DATA) $(PKGCONFIG) $(LIBDIR)/pkgconfig/$(PKGCONFIG)
 
 uninstall:
-	$(RM) -f $(LIBDIR)/pkgconfig/$(PKGCONFIG)
 	$(RM) -f $(LIBDIR)/$(LIBRARY)
 	$(RM) -f $(INCDIR)/$(HEADER)
 
@@ -119,4 +121,7 @@ llib-lpnetcdf.ln: $(LIB_CSRCS)
 lint: llib-lpnetcdf.ln
 	$(LINT.c) t_nc.c llib-lpnetcdf.ln
 
+ncx.h: ncx_h.m4
+	$(M4) $(M4FLAGS) $< >$@
+
 include $(srcdir)/depend
diff --git a/src/lib/attr.m4 b/src/lib/attr.m4
index 2f1c59a..49ed74d 100644
--- a/src/lib/attr.m4
+++ b/src/lib/attr.m4
@@ -7,10 +7,10 @@ dnl
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id$ */
+/* $Id: attr.m4 2589 2016-10-30 17:42:43Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -109,20 +109,16 @@ ncmpii_new_x_NC_attr(NC_string  *strp,
 NC_new_attr(name,type,count,value)
  */
 static NC_attr *
-ncmpii_new_NC_attr(const char *uname,  /* attribute name (NULL terminated) */
+ncmpii_new_NC_attr(const char *name,  /* normalized attribute name (NULL terminated) */
                    nc_type     type,
                    MPI_Offset  nelems)
 {
     NC_string *strp;
     NC_attr *attrp;
 
-    char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
-    if (name == NULL) return NULL;
-
     assert(name != NULL && *name != 0);
 
     strp = ncmpii_new_NC_string(strlen(name), name);
-    free(name);
     if (strp == NULL) return NULL;
 
     attrp = ncmpii_new_x_NC_attr(strp, type, nelems);
@@ -192,7 +188,8 @@ ncmpii_dup_NC_attrarray(NC_attrarray *ncap, const NC_attrarray *ref)
     }
 
     if (ref->nalloc > 0) {
-        ncap->value = (NC_attr **) NCI_Calloc((size_t)ref->nalloc, sizeof(NC_attr*));
+        ncap->value = (NC_attr **) NCI_Calloc((size_t)ref->nalloc,
+                                              sizeof(NC_attr*));
         if (ncap->value == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
         ncap->nalloc = ref->nalloc;
     }
@@ -297,56 +294,47 @@ NC_attrarray0(NC  *ncp,
  */
 int
 ncmpii_NC_findattr(const NC_attrarray *ncap,
-                   const char         *uname)
+                   const char         *name) /* normalized string */
 {
     int i;
-    size_t nchars;
-    char *name;
+    size_t nchars=strlen(name);
 
     assert(ncap != NULL);
 
     if (ncap->ndefined == 0) return -1; /* none created yet */
 
-    name = (char *)utf8proc_NFC((const unsigned char *)uname);
-    nchars = strlen(name);
+    /* already checked before entering this API
+    if (name == NULL || *name == 0) return -1;
+    */
 
     for (i=0; i<ncap->ndefined; i++) {
         if (ncap->value[i]->name->nchars == nchars &&
             strncmp(ncap->value[i]->name->cp, name, nchars) == 0) {
-            free(name);
             return i;
         }
     }
-    free(name);
 
     return -1;
 }
 
 
+/*----< NC_lookupattr() >----------------------------------------------------*/
 /*
- * Look up by ncid, varid and name, return NULL if not found
+ * Look up by ncid, ncap, and name
  */
 static int
-NC_lookupattr(int ncid,
-    int varid,
-    const char *name, /* attribute name */
-    NC_attr **attrpp) /* modified on return */
+NC_lookupattr(NC_attrarray  *ncap,
+              const char    *name,   /* normalized attribute name */
+              NC_attr      **attrpp) /* modified on return */
 {
-    int indx, status;
-    NC *ncp;
-    NC_attrarray *ncap;
+    int indx;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if(status != NC_NOERR)
-        return status;
-
-    ncap = NC_attrarray0(ncp, varid);
-    if(ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+    /* validity of ncid and ncap has already been checked */
 
     indx = ncmpii_NC_findattr(ncap, name);
-    if(indx == -1) DEBUG_RETURN_ERROR(NC_ENOTATT)
+    if (indx == -1) DEBUG_RETURN_ERROR(NC_ENOTATT)
 
-    if(attrpp != NULL)
+    if (attrpp != NULL)
         *attrpp = ncap->value[indx];
 
     return NC_NOERR;
@@ -355,20 +343,20 @@ NC_lookupattr(int ncid,
 /* Public */
 
 /*----< ncmpi_inq_attname() >------------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_attname(int   ncid,
                   int   varid,
                   int   attid,
-                  char *name)
-
+                  char *name)   /* out */
 {
-    int status;
+    int err;
     NC *ncp;
     NC_attrarray *ncap;
     NC_attr *attrp;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
     ncap = NC_attrarray0(ncp, varid);
     if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
@@ -376,8 +364,9 @@ ncmpi_inq_attname(int   ncid,
     attrp = elem_NC_attrarray(ncap, attid);
     if (attrp == NULL) DEBUG_RETURN_ERROR(NC_ENOTATT)
 
+    if (name == NULL) DEBUG_RETURN_ERROR(NC_EINVAL)
+
     /* in PnetCDF, name->cp is always NULL character terminated */
-    assert(name != NULL);
     strcpy(name, attrp->name->cp);
 
     return NC_NOERR;
@@ -385,23 +374,33 @@ ncmpi_inq_attname(int   ncid,
 
 
 /*----< ncmpi_inq_attid() >--------------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_attid(int         ncid,
                 int         varid,
                 const char *name,
-                int        *attidp)
+                int        *attidp)  /* out */
 {
-    int indx, status;
+    int indx, err;
+    char *nname=NULL; /* normalized name */
     NC *ncp;
     NC_attrarray *ncap;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
     ncap = NC_attrarray0(ncp, varid);
     if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
 
-    indx = ncmpii_NC_findattr(ncap, name);
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME)
+        DEBUG_RETURN_ERROR(NC_EBADNAME)
+
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    indx = ncmpii_NC_findattr(ncap, nname);
+    free(nname);
     if (indx == -1) DEBUG_RETURN_ERROR(NC_ENOTATT)
 
     if (attidp != NULL)
@@ -411,6 +410,7 @@ ncmpi_inq_attid(int         ncid,
 }
 
 /*----< ncmpi_inq_att() >----------------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_att(int         ncid,
               int         varid,
@@ -418,11 +418,28 @@ ncmpi_inq_att(int         ncid,
               nc_type    *datatypep,
               MPI_Offset *lenp)
 {
-    int status;
+    int err;
+    char *nname=NULL;    /* normalized name */
+    NC *ncp;
     NC_attr *attrp;
+    NC_attrarray *ncap;
+
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+
+    ncap = NC_attrarray0(ncp, varid);
+    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME)
+        DEBUG_RETURN_ERROR(NC_EBADNAME)
+
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
 
-    status = NC_lookupattr(ncid, varid, name, &attrp);
-    if (status != NC_NOERR) return status;
+    err = NC_lookupattr(ncap, nname, &attrp);
+    free(nname);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
     if (datatypep != NULL)
         *datatypep = attrp->type;
@@ -434,6 +451,7 @@ ncmpi_inq_att(int         ncid,
 }
 
 /*----< ncmpi_inq_atttype() >------------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_atttype(int         ncid,
                   int         varid,
@@ -444,6 +462,7 @@ ncmpi_inq_atttype(int         ncid,
 }
 
 /*----< ncmpi_inq_attlen() >-------------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_attlen(int         ncid,
                  int         varid,
@@ -462,92 +481,166 @@ ncmpi_rename_att(int         ncid,
                  const char *name,
                  const char *newname)
 {
-    int indx, file_ver, status, err, mpireturn;
+    int indx, err;
+    char *nname=NULL;    /* normalized name */
+    char *nnewname=NULL; /* normalized newname */
     NC *ncp;
-    NC_attrarray *ncap;
-    NC_attr *attrp;
-
-    /* sortof inline clone of NC_lookupattr() */
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
-
-    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM)
+    NC_attrarray *ncap=NULL;
+    NC_attr *attrp=NULL;
+    NC_string *newStr=NULL;
+
+    /* check whether ncid is valid */
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+
+    /* check whether file's write permission */
+    if (NC_readonly(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EPERM)
+        goto err_check;
+    }
 
     ncap = NC_attrarray0(ncp, varid);
-    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+    if (ncap == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTVAR)
+        goto err_check;
+    }
 
-    file_ver = 1;
-    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
-        file_ver = 2;
-    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
-        file_ver = 5;
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME) {
+        DEBUG_ASSIGN_ERROR(err, NC_EBADNAME)
+        goto err_check;
+    }
 
-    status = ncmpii_NC_check_name(newname, file_ver);
-    if (status != NC_NOERR) return status;
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
+    }
 
-    indx = ncmpii_NC_findattr(ncap, name);
-    if (indx < 0) DEBUG_RETURN_ERROR(NC_ENOTATT)
+    indx = ncmpii_NC_findattr(ncap, nname);
+    free(nname);
+    if (indx < 0) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTATT)
+        goto err_check;
+    }
 
     attrp = ncap->value[indx];
-    /* end inline clone NC_lookupattr() */
 
-    if (ncmpii_NC_findattr(ncap, newname) >= 0)
+    if (newname == NULL || *newname == 0 || strlen(newname) > NC_MAX_NAME) {
+        DEBUG_ASSIGN_ERROR(err, NC_EBADNAME)
+        goto err_check;
+    }
+
+    /* check whether new name is legal */
+    err = ncmpii_NC_check_name(newname, ncp->format);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
+
+    /* create a normalized character string */
+    nnewname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)newname);
+    if (nnewname == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
+    }
+
+    if (ncmpii_NC_findattr(ncap, nnewname) >= 0) {
         /* name in use */
-        DEBUG_RETURN_ERROR(NC_ENAMEINUSE)
+        DEBUG_ASSIGN_ERROR(err, NC_ENAMEINUSE)
+        goto err_check;
+    }
 
-    if (NC_indef(ncp)) {
-        NC_string *newStr = ncmpii_new_NC_string(strlen(newname), newname);
-        if (newStr == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+    if (! NC_indef(ncp) && /* when file is in data mode */
+        attrp->name->nchars < (MPI_Offset)strlen(nnewname)) {
+        /* must in define mode when nnewname is longer */
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+        goto err_check;
+    }
 
-        ncmpii_free_NC_string(attrp->name);
-        attrp->name = newStr;
-        return NC_NOERR;
+    newStr = ncmpii_new_NC_string(strlen(nnewname), nnewname);
+    if (newStr == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
     }
-    /* else, not in define mode.
-     * If called in data mode (collective or independent), this function must
-     * be called collectively, i.e. all processes must participate
-     */
+
+err_check:
+    if (nnewname != NULL) free(nnewname);
 
     if (ncp->safe_mode) {
-        int nchars = (int) strlen(newname);
-        TRACE_COMM(MPI_Bcast)(&nchars, 1, MPI_INT, 0, ncp->nciop->comm);
+        int root_varid, status, mpireturn;
+        char root_name[NC_MAX_NAME];
+        
+        /* check if name is consistent among all processes */
+        if (name == NULL || *name == 0)
+            root_name[0] = 0;
+        else
+            strncpy(root_name, name, NC_MAX_NAME);
+        TRACE_COMM(MPI_Bcast)(root_name, NC_MAX_NAME, MPI_CHAR, 0, ncp->nciop->comm);         
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && strcmp(root_name, name))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_NAME)
+
+        /* check if newname is consistent among all processes */
+        if (newname == NULL || *newname == 0)
+            root_name[0] = 0;
+        else
+            strncpy(root_name, newname, NC_MAX_NAME);
+        TRACE_COMM(MPI_Bcast)(root_name, NC_MAX_NAME, MPI_CHAR, 0, ncp->nciop->comm);         
         if (mpireturn != MPI_SUCCESS)
-            return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && strcmp(root_name, newname))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_NAME)
 
-        if (nchars != strlen(newname)) {
-            /* newname's length is inconsistent with root's */
-            printf("Warning: attribute name(%s) used in %s() is inconsistent\n",
-                   newname, __func__);
-            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_ATTR_NAME)
-        }
+        /* check if varid is consistent across all processes */
+        root_varid = varid;
+        TRACE_COMM(MPI_Bcast)(&root_varid, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && root_varid != varid)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FNC_ARGS)
+
+        /* find min error code across processes */ 
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);  
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        if (err == NC_NOERR) err = status;
     }
 
-    /* ncmpii_set_NC_string() will check for strlen(newname) > nchars error */
-    err = ncmpii_set_NC_string(attrp->name, newname);
-    if (status == NC_NOERR) status = err;
+    if (err != NC_NOERR) {
+        if (newStr != NULL) ncmpii_free_NC_string(newStr);
+        return err;
+    }   
 
-    /* PnetCDF expects all processes use the same name, However, when names
-     * are not the same, only root's value is significant. Broadcast the
-     * new name at root to overwrite new names at other processes.
-     * (This API is collective if called in data mode)
-     */
-    TRACE_COMM(MPI_Bcast)(attrp->name->cp, (int)attrp->name->nchars, MPI_CHAR, 0,
-                          ncp->nciop->comm);
+    assert(attrp != NULL);
 
-    /* Let root write the entire header to the file. Note that we cannot just
-     * update the variable name in its space occupied in the file header,
-     * because if the file space occupied by the name shrinks, all the metadata
-     * following it must be moved ahead.
-     */
-    err = ncmpii_write_header(ncp);
-    if (status == NC_NOERR) status = err;
+    /* replace the old name with new name */
+    ncmpii_free_NC_string(attrp->name);
+    attrp->name = newStr;
+
+    if (! NC_indef(ncp)) { /* when file is in data mode */
+        /* Let root write the entire header to the file. Note that we cannot
+         * just update the variable name in its space occupied in the file
+         * header, because if the file space occupied by the name shrinks, all
+         * the metadata following it must be moved ahead.
+         */
+        err = ncmpii_write_header(ncp);
+        if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+    }
 
-    return status;
+    return err;
 }
 
 
 /*----< ncmpi_copy_att() >----------------------------------------------------*/
-/* This API is collective if called in data mode */
+/* This API is collective for processes that opened ncid_out.
+ * If the attribute does not exist in ncid_out, then this API must be called
+ * when ncid_out is in define mode.
+ * If the attribute does exist in ncid_out and the attribute in ncid_in is
+ * larger than the one in ncid_out, then this API must be called when ncid_out
+ * is in define mode.
+ */
 int
 ncmpi_copy_att(int         ncid_in,
                int         varid_in,
@@ -555,124 +648,269 @@ ncmpi_copy_att(int         ncid_in,
                int         ncid_out,
                int         varid_out)
 {
-    int indx, status, mpireturn;
-    NC *ncp;
-    NC_attrarray *ncap;
-    NC_attr *iattrp, *attrp, *old=NULL;
-
-    status = NC_lookupattr(ncid_in, varid_in, name, &iattrp);
-    if (status != NC_NOERR) return status;
-
-    status = ncmpii_NC_check_id(ncid_out, &ncp);
-    if (status != NC_NOERR) return status;
-
-    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM)
+    int indx=0, err;
+    char *nname=NULL;    /* normalized name */
+    NC *ncp_in, *ncp_out;
+    NC_attrarray *ncap_out=NULL, *ncap_in;
+    NC_attr *iattrp, *attrp=NULL;
+
+    err = ncmpii_NC_check_id(ncid_in, &ncp_in);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+
+    err = ncmpii_NC_check_id(ncid_out, &ncp_out);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+
+    ncap_in = NC_attrarray0(ncp_in, varid_in);
+    if (ncap_in == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTVAR)
+        goto err_check;
+    }
 
-    ncap = NC_attrarray0(ncp, varid_out);
-    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+    ncap_out = NC_attrarray0(ncp_out, varid_out);
+    if (ncap_out == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTVAR)
+        goto err_check;
+    }
 
-    indx = ncmpii_NC_findattr(ncap, name);
-    if (indx >= 0) { /* name in use */
-        if (!NC_indef(ncp)) {
-            /* if called in data mode (collective or independent), this
-             * function must be called collectively, i.e. all processes must
-             * participate
-             */
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME) {
+        DEBUG_ASSIGN_ERROR(err, NC_EBADNAME)
+        goto err_check;
+    }
 
-            attrp = ncap->value[indx]; /* convenience */
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
+    }
 
-            if (iattrp->xsz > attrp->xsz) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
-            /* else, we can reuse existing without redef */
+    err = NC_lookupattr(ncap_in, nname, &iattrp);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
 
-            if (iattrp->xsz != (int)iattrp->xsz) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    if (iattrp->xsz != (int)iattrp->xsz) {
+        DEBUG_ASSIGN_ERROR(err, NC_EINTOVERFLOW)
+        goto err_check;
+    }
 
-            attrp->xsz = iattrp->xsz;
-            attrp->type = iattrp->type;
-            attrp->nelems = iattrp->nelems;
+    /* check whether file's write permission */
+    if (NC_readonly(ncp_out)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EPERM)
+        goto err_check;
+    }
 
-            memcpy(attrp->xvalue, iattrp->xvalue, (size_t)iattrp->xsz);
+    indx = ncmpii_NC_findattr(ncap_out, nname);
 
-            /* PnetCDF expects all processes use the same name, However, when
-             * new attributes are not the same, only root's value is
-             * significant. Broadcast the new attribute at root to overwrite
-             * new names at other processes.
-             */
-            TRACE_COMM(MPI_Bcast)((void*)attrp->xvalue, (int)attrp->xsz,
-                                  MPI_CHAR, 0, ncp->nciop->comm);
-            if (mpireturn != MPI_SUCCESS)
-                return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
-
-            /* Let root write the entire header to the file. Note that we
-             * cannot just update the variable name in its space occupied in
-             * the file header, because if the file space occupied by the name
-             * shrinks, all the metadata following it must be moved ahead.
-             */
-            return ncmpii_write_header(ncp);
+    if (indx >= 0) { /* name in use in ncid_out */
+        if (!NC_indef(ncp_out) &&  /* not allowed in data mode */
+            iattrp->xsz > ncap_out->value[indx]->xsz) {
+            DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+            goto err_check;
         }
-        /* else, redefine using existing array slot */
-        old = ncap->value[indx];
     }
-    else {
-        if (!NC_indef(ncp)) /* add new attribute is not allowed in data mode */
-            DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
-
-        if (ncap->ndefined >= NC_MAX_ATTRS)
-            DEBUG_RETURN_ERROR(NC_EMAXATTS)
+    else { /* attribute does not exit in ncid_out */
+        if (!NC_indef(ncp_out)) { /* add new attribute is not allowed in data mode */
+            DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+            goto err_check;
+        }
+        if (ncap_out->ndefined >= NC_MAX_ATTRS) {
+            DEBUG_ASSIGN_ERROR(err, NC_EMAXATTS)
+            goto err_check;
+        }
     }
 
-    attrp = ncmpii_new_NC_attr(name, iattrp->type, iattrp->nelems);
-    if (attrp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+err_check:
+    if (ncp_out->safe_mode) {
+        int root_ids[3], status, mpireturn;
+        char root_name[NC_MAX_NAME];
+
+        /* check if name is consistent among all processes */
+        if (name == NULL || *name == 0)
+            root_name[0] = 0;
+        else
+            strncpy(root_name, name, NC_MAX_NAME);
+        TRACE_COMM(MPI_Bcast)(root_name, NC_MAX_NAME, MPI_CHAR, 0, ncp_out->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && strcmp(root_name, name))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_NAME)
+
+        /* check if varid_in, ncid_out, varid_out, are consistent across all
+         * processes */
+        root_ids[0] = varid_in;
+        root_ids[1] = ncid_out;
+        root_ids[2] = varid_out;
+        TRACE_COMM(MPI_Bcast)(&root_ids, 3, MPI_INT, 0, ncp_out->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && (root_ids[0] != varid_in ||
+            root_ids[1] != ncid_out || root_ids[2] != varid_out))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FNC_ARGS)
+
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp_out->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        }
 
-    memcpy(attrp->xvalue, iattrp->xvalue, (size_t)iattrp->xsz);
+        if (err == NC_NOERR) err = status;
+    }
 
-    if (indx >= 0) {
-        assert(old != NULL);
-        ncap->value[indx] = attrp;
-        ncmpii_free_NC_attr(old);
+    if (err != NC_NOERR) {
+        if (nname != NULL) free(nname);
+        return err;
     }
-    else {
-        status = incr_NC_attrarray(ncap, attrp);
-        if (status != NC_NOERR) {
+    assert(ncap_out != NULL);
+    assert(nname != NULL);
+
+    if (indx >= 0) { /* name in use in ncid_out */
+        /* reuse existing attribute array slot without redef */
+        attrp = ncap_out->value[indx];
+
+        if (iattrp->xsz > attrp->xsz) {
+            /* Note the whole attribute object is allocated as one contiguous
+             * chunk, so we cannot realloc attrp->xvalue only
+             */
             ncmpii_free_NC_attr(attrp);
-            return status;
+            attrp = ncmpii_new_NC_attr(nname, iattrp->type, iattrp->nelems);
+            free(nname);
+            if (attrp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+            ncap_out->value[indx] = attrp;
+        }
+        else {
+            free(nname);
+            attrp->xsz    = iattrp->xsz;
+            attrp->type   = iattrp->type;
+            attrp->nelems = iattrp->nelems;
         }
     }
-    return NC_NOERR;
+    else { /* attribute does not exit in ncid_out */
+        attrp = ncmpii_new_NC_attr(nname, iattrp->type, iattrp->nelems);
+        free(nname);
+        if (attrp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+        err = incr_NC_attrarray(ncap_out, attrp);
+        if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+    }
+
+    if (iattrp->xsz > 0)
+        memcpy(attrp->xvalue, iattrp->xvalue, (size_t)iattrp->xsz);
+
+    if (!NC_indef(ncp_out)) { /* called in data mode */
+        /* Let root write the entire header to the file. Note that we
+         * cannot just update the variable name in its space occupied in
+         * the file header, because if the file space occupied by the name
+         * shrinks, all the metadata following it must be moved ahead.
+         */
+        err = ncmpii_write_header(ncp_out); /* update file header */
+        if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+    }
+
+    return err;
 }
 
 /*----< ncmpi_del_att() >---------------------------------------------------*/
+/* This is a collective subroutine and must be called in define mode */
 int
 ncmpi_del_att(int         ncid,
               int         varid,
               const char *name)
 {
-    int status, attrid;
+    int err, attrid=-1;
+    char *nname=NULL; /* normalized name */
     NC *ncp;
-    NC_attrarray *ncap;
+    NC_attrarray *ncap=NULL;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
-    if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+    if (!NC_indef(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+        goto err_check;
+    }
 
     ncap = NC_attrarray0(ncp, varid);
-    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+    if (ncap == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTVAR)
+        goto err_check;
+    }
 
-    attrid = ncmpii_NC_findattr(ncap, name);
-    if (attrid == -1) DEBUG_RETURN_ERROR(NC_ENOTATT)
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME) {
+        DEBUG_ASSIGN_ERROR(err, NC_EBADNAME)
+        goto err_check;
+    }
+
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
+    }
+
+    attrid = ncmpii_NC_findattr(ncap, nname);
+    free(nname);
+    if (attrid == -1) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTATT)
+        goto err_check;
+    }
 
     /* deleting attribute _FillValue means disabling fill mode */
-    if (!strcmp(name, _FillValue)) {
+    if (varid != NC_GLOBAL && !strcmp(name, _FillValue)) {
         NC_var *varp;
-        status = ncmpii_NC_lookupvar(ncp, varid, &varp);
-        if (status != NC_NOERR) return status;
+        err = ncmpii_NC_lookupvar(ncp, varid, &varp);
+        if (err != NC_NOERR) {
+            DEBUG_TRACE_ERROR
+            goto err_check;
+        }
         varp->no_fill = 1;
     }
 
+err_check:
+    if (ncp->safe_mode) {
+        int root_varid, status, mpireturn;
+        char root_name[NC_MAX_NAME];
+
+        /* check if name is consistent among all processes */
+        if (name == NULL || *name == 0)
+            root_name[0] = 0;
+        else
+            strncpy(root_name, name, NC_MAX_NAME);
+        TRACE_COMM(MPI_Bcast)(root_name, NC_MAX_NAME, MPI_CHAR, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && strcmp(root_name, name))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_NAME)
+
+        /* check if varid is consistent across all processes */
+        root_varid = varid;
+        TRACE_COMM(MPI_Bcast)(&root_varid, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && root_varid != varid)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FNC_ARGS)
+
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        if (err == NC_NOERR) err = status;
+    }
+
+    if (err != NC_NOERR) return err;
+    assert(ncap != NULL);
+
+    /* delete attribute */
     ncmpii_free_NC_attr(ncap->value[attrid]);
 
     /* shuffle down */
-    for (; attrid < ncap->ndefined; attrid++)
+    for (; attrid < ncap->ndefined-1; attrid++)
         ncap->value[attrid] = ncap->value[attrid+1];
 
     /* decrement count */
@@ -681,599 +919,606 @@ ncmpi_del_att(int         ncid,
     return NC_NOERR;
 }
 
-static nc_type longtype = (SIZEOF_LONG == SIZEOF_INT ? NC_INT : NC_INT64);
+include(`foreach.m4')dnl
+include(`utils.m4')dnl
 
-/* ncmpi_pad_xxx APIs are only applicable for filetypes of size smaller
- * than 4 bytes
- */
-dnl
-dnl PAD_GETN_FILETYPE(filetype)
-dnl
-define(`PAD_GETN_FILETYPE',dnl
-`dnl
-/*----< ncmpix_pad_getn_$1() >-----------------------------------------------*/
-inline static int
-ncmpix_pad_getn_$1(const void **xpp,
-                   MPI_Offset   nelems,
-                   void        *tp,
-                   nc_type      buftype)
+/*----< ncmpi_get_att() >-----------------------------------------------------*/
+/* This is an independent subroutine */
+/* user buffer data type matches the external type defined in file */
+int
+ncmpi_get_att(int         ncid,
+              int         varid,
+              const char *name,
+              void       *buf)
 {
-    switch(buftype) {
-        case NC_CHAR:
-        case NC_BYTE:
-            return ncmpix_pad_getn_$1_schar (xpp, nelems, (schar*)tp);
-        case NC_UBYTE:
-            return ncmpix_pad_getn_$1_uchar (xpp, nelems, (uchar*)tp);
-        case NC_SHORT:
-            return ncmpix_pad_getn_$1_short (xpp, nelems, (short*)tp);
-        case NC_USHORT:
-            return ncmpix_pad_getn_$1_ushort(xpp, nelems, (ushort*)tp);
-        case NC_INT:
-            return ncmpix_pad_getn_$1_int   (xpp, nelems, (int*)tp);
-        case NC_UINT:
-            return ncmpix_pad_getn_$1_uint  (xpp, nelems, (uint*)tp);
-        case NC_FLOAT:
-            return ncmpix_pad_getn_$1_float (xpp, nelems, (float*)tp);
-        case NC_DOUBLE:
-            return ncmpix_pad_getn_$1_double(xpp, nelems, (double*)tp);
-        case NC_INT64:
-            return ncmpix_pad_getn_$1_longlong (xpp, nelems, (longlong*)tp);
-        case NC_UINT64:
-            return ncmpix_pad_getn_$1_ulonglong(xpp, nelems, (ulonglong*)tp);
-        default: fprintf(stderr, "Error: bad buftype(%d) in %s\n",buftype,__func__);
+    int err;
+    nc_type xtype;  /* external NC data type */
+
+    /* obtain variable external data type */
+    err = ncmpi_inq_atttype(ncid, varid, name, &xtype);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+
+    switch(xtype) {
+        case NC_CHAR:   return ncmpi_get_att_text     (ncid, varid, name, buf);
+        case NC_BYTE:   return ncmpi_get_att_schar    (ncid, varid, name, buf);
+        case NC_UBYTE:  return ncmpi_get_att_uchar    (ncid, varid, name, buf);
+        case NC_SHORT:  return ncmpi_get_att_short    (ncid, varid, name, buf);
+        case NC_USHORT: return ncmpi_get_att_ushort   (ncid, varid, name, buf);
+        case NC_INT:    return ncmpi_get_att_int      (ncid, varid, name, buf);
+        case NC_UINT:   return ncmpi_get_att_uint     (ncid, varid, name, buf);
+        case NC_FLOAT:  return ncmpi_get_att_float    (ncid, varid, name, buf);
+        case NC_DOUBLE: return ncmpi_get_att_double   (ncid, varid, name, buf);
+        case NC_INT64:  return ncmpi_get_att_longlong (ncid, varid, name, buf);
+        case NC_UINT64: return ncmpi_get_att_ulonglong(ncid, varid, name, buf);
+        default: return NC_EBADTYPE;
     }
-    return NC_EBADTYPE;
 }
-')dnl
-
-PAD_GETN_FILETYPE(schar)
-PAD_GETN_FILETYPE(uchar)
-PAD_GETN_FILETYPE(short)
-PAD_GETN_FILETYPE(ushort)
 
-dnl
-dnl GETN_FILETYPE(filetype)
-dnl
-define(`GETN_FILETYPE',dnl
-`dnl
-/*----< ncmpix_getn_$1() >---------------------------------------------------*/
-inline static int
-ncmpix_getn_$1(const void **xpp,
-               MPI_Offset   nelems,
-               void        *tp,
-               nc_type      buftype)
+/*----< ncmpi_get_att_text() >-------------------------------------------------*/
+/* This is an independent subroutine.
+ * Note this API will never return NC_ERANGE error, as text is not convertible
+ * to numerical types.
+ */
+int
+ncmpi_get_att_text(int         ncid,
+                   int         varid,
+                   const char *name,
+                   char       *buf)
 {
-    switch(buftype) {
-        case NC_CHAR:
-        case NC_BYTE:
-            return ncmpix_getn_$1_schar (xpp, nelems, (schar*)tp);
-        case NC_UBYTE:
-            return ncmpix_getn_$1_uchar (xpp, nelems, (uchar*)tp);
-        case NC_SHORT:
-            return ncmpix_getn_$1_short (xpp, nelems, (short*)tp);
-        case NC_USHORT:
-            return ncmpix_getn_$1_ushort(xpp, nelems, (ushort*)tp);
-        case NC_INT:
-            return ncmpix_getn_$1_int   (xpp, nelems, (int*)tp);
-        case NC_UINT:
-            return ncmpix_getn_$1_uint  (xpp, nelems, (uint*)tp);
-        case NC_FLOAT:
-            return ncmpix_getn_$1_float (xpp, nelems, (float*)tp);
-        case NC_DOUBLE:
-            return ncmpix_getn_$1_double(xpp, nelems, (double*)tp);
-        case NC_INT64:
-            return ncmpix_getn_$1_longlong (xpp, nelems, (longlong*)tp);
-        case NC_UINT64:
-            return ncmpix_getn_$1_ulonglong(xpp, nelems, (ulonglong*)tp);
-        default: fprintf(stderr, "Error: bad buftype(%d) in %s\n",buftype,__func__);
-    }
-    return NC_EBADTYPE;
-}
-')dnl
+    int      err;
+    char    *nname=NULL; /* normalized name */
+    NC      *ncp;
+    NC_attr *attrp;
+    NC_attrarray *ncap=NULL;
+    const void *xp;
 
-GETN_FILETYPE(int)
-GETN_FILETYPE(uint)
-GETN_FILETYPE(float)
-GETN_FILETYPE(double)
-GETN_FILETYPE(int64)
-GETN_FILETYPE(uint64)
+    /* get the file ID */
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
-/*----< ncmpix_pad_getn() >--------------------------------------------------*/
-/* padding only applicable to file types of size smaller than 4 bytes */
-inline static int
-ncmpix_pad_getn(const void **xpp,
-                MPI_Offset   nelems,
-                void        *tp,
-                nc_type      filetype,
-                nc_type      buftype)
-{
-    /* get n elements from (filetype*)*xpp to (buftype*)tp */
-    /* Checking for character-number conversion should have already been done */
+    /* check if varid is valid */
+    ncap = NC_attrarray0(ncp, varid);
+    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
 
-    switch(filetype) {
-        case NC_CHAR:
-        case NC_BYTE:
-            return ncmpix_pad_getn_schar (xpp, nelems, tp, buftype);
-        case NC_UBYTE:
-            return ncmpix_pad_getn_uchar (xpp, nelems, tp, buftype);
-        case NC_SHORT:
-            return ncmpix_pad_getn_short (xpp, nelems, tp, buftype);
-        case NC_USHORT:
-            return ncmpix_pad_getn_ushort(xpp, nelems, tp, buftype);
-        case NC_INT:
-            return ncmpix_getn_int       (xpp, nelems, tp, buftype);
-        case NC_UINT:
-            return ncmpix_getn_uint      (xpp, nelems, tp, buftype);
-        case NC_FLOAT:
-            return ncmpix_getn_float     (xpp, nelems, tp, buftype);
-        case NC_DOUBLE:
-            return ncmpix_getn_double    (xpp, nelems, tp, buftype);
-        case NC_INT64:
-            return ncmpix_getn_int64     (xpp, nelems, tp, buftype);
-        case NC_UINT64:
-            return ncmpix_getn_uint64    (xpp, nelems, tp, buftype);
-        default: fprintf(stderr, "Error: bad filetype(%d) in %s\n",filetype,__func__);
-    }
-    return NC_EBADTYPE;
-}
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME)
+        DEBUG_RETURN_ERROR(NC_EBADNAME)
 
-/*----< ncmpii_get_att() >---------------------------------------------------*/
-static int
-ncmpii_get_att(int         ncid,
-               int         varid,
-               const char *name,
-               void       *tp,       /* I/O buffer */
-               nc_type     buftype)  /* I/O buffer data type */
-{
-    int status;
-    NC_attr *attrp;
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
 
-    status = NC_lookupattr(ncid, varid, name, &attrp);
-    if (status != NC_NOERR) return status;
+    err = NC_lookupattr(ncap, nname, &attrp);
+    free(nname);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
     if (attrp->nelems == 0) return NC_NOERR;
 
     /* No character conversions are allowed. */
-    if (attrp->type != buftype &&
-        (attrp->type == NC_CHAR || buftype == NC_CHAR))
-        DEBUG_RETURN_ERROR(NC_ECHAR)
-
-    const void *xp = attrp->xvalue;
-    return ncmpix_pad_getn(&xp, attrp->nelems, tp, attrp->type, buftype);
-}
+    if (attrp->type != NC_CHAR) DEBUG_RETURN_ERROR(NC_ECHAR)
 
-/*----< ncmpi_get_att() >-----------------------------------------------------*/
-int
-ncmpi_get_att(int         ncid,
-              int         varid,
-              const char *name,
-              void       *value)
-{
-    int status;
-    nc_type atttype;
-
-    status = ncmpi_inq_atttype(ncid, varid, name, &atttype);
-    if (status != NC_NOERR) return status;
+    if (buf == NULL) DEBUG_RETURN_ERROR(NC_EINVAL)
 
-    return ncmpii_get_att(ncid, varid, name, value, atttype);
+    xp = attrp->xvalue;
+    return ncmpix_pad_getn_text(&xp, attrp->nelems, (char*)buf);
 }
 
 dnl
-dnl GET_ATT_TYPE(fntype, ext_buftype, nc_buftype)
+dnl GET_ATT(fntype)
 dnl
-define(`GET_ATT_TYPE',dnl
+define(`GET_ATT',dnl
 `dnl
 /*----< ncmpi_get_att_$1() >-------------------------------------------------*/
+/* This is an independent subroutine */
 int
-ncmpi_get_att_$1(int ncid, int varid, const char  *name, $2 *value)
+ncmpi_get_att_$1(int             ncid,
+                 int             varid,
+                 const char     *name,
+                 FUNC2ITYPE($1) *buf)
 {
-    return ncmpii_get_att(ncid, varid, name, value, $3);
-}
-')dnl
+    int            err=NC_NOERR;
+    char           *nname=NULL; /* normalized name */
+    NC             *ncp;
+    NC_attr        *attrp;
+    NC_attrarray   *ncap=NULL;
+    const void     *xp;
+    MPI_Offset      nelems;
 
-GET_ATT_TYPE(text,      char,               NC_CHAR)
-GET_ATT_TYPE(schar,     signed char,        NC_BYTE)
-GET_ATT_TYPE(uchar,     unsigned char,      NC_UBYTE)
-GET_ATT_TYPE(ubyte,     unsigned char,      NC_UBYTE)
-GET_ATT_TYPE(short,     short,              NC_SHORT)
-GET_ATT_TYPE(ushort,    unsigned short,     NC_USHORT)
-GET_ATT_TYPE(int,       int,                NC_INT)
-GET_ATT_TYPE(uint,      unsigned int,       NC_UINT)
-GET_ATT_TYPE(long,      long,               longtype)
-GET_ATT_TYPE(float,     float,              NC_FLOAT)
-GET_ATT_TYPE(double,    double,             NC_DOUBLE)
-GET_ATT_TYPE(longlong,  long long,          NC_INT64)
-GET_ATT_TYPE(ulonglong, unsigned long long, NC_UINT64)
+    /* get the file ID */
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
-dnl
-dnl PAD_PUTN_FILETYPE(ftype)
-dnl
-define(`PAD_PUTN_FILETYPE',dnl
-`dnl
-/*----< ncmpix_pad_putn_$1() >-----------------------------------------------*/
-inline static int
-ncmpix_pad_putn_$1(void       **xpp,
-                   MPI_Offset   nelems,
-                   const void  *tp,
-                   nc_type      btype)
-{
-    switch(btype) {
-        case NC_CHAR:
+    /* check if varid is valid */
+    ncap = NC_attrarray0(ncp, varid);
+    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME)
+        DEBUG_RETURN_ERROR(NC_EBADNAME)
+
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    err = NC_lookupattr(ncap, nname, &attrp);
+    free(nname);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+
+    if (attrp->nelems == 0) return NC_NOERR;
+    nelems = attrp->nelems;
+
+    /* No character conversions are allowed. */
+    if (attrp->type == NC_CHAR) DEBUG_RETURN_ERROR(NC_ECHAR)
+
+    if (buf == NULL) DEBUG_RETURN_ERROR(NC_EINVAL)
+
+    xp = attrp->xvalue;
+
+    switch(attrp->type) {
         case NC_BYTE:
-            return ncmpix_pad_putn_$1_schar (xpp, nelems, (schar*)tp);
+            ifelse(`$1',`uchar',
+           `if (ncp->format < 5) { /* no NC_ERANGE check */
+                /* note this is not ncmpix_getn_NC_BYTE_$1 */
+                return ncmpix_pad_getn_NC_UBYTE_$1(&xp, nelems, buf);
+            } else')
+                return ncmpix_pad_getn_NC_BYTE_$1 (&xp, nelems, buf);
         case NC_UBYTE:
-            return ncmpix_pad_putn_$1_uchar (xpp, nelems, (uchar*)tp);
+            return ncmpix_pad_getn_NC_UBYTE_$1 (&xp, nelems, buf);
         case NC_SHORT:
-            return ncmpix_pad_putn_$1_short (xpp, nelems, (short*)tp);
+            return ncmpix_pad_getn_NC_SHORT_$1 (&xp, nelems, buf);
         case NC_USHORT:
-            return ncmpix_pad_putn_$1_ushort(xpp, nelems, (ushort*)tp);
+            return ncmpix_pad_getn_NC_USHORT_$1(&xp, nelems, buf);
         case NC_INT:
-            return ncmpix_pad_putn_$1_int   (xpp, nelems, (int*)tp);
+            return ncmpix_getn_NC_INT_$1   (&xp, nelems, buf);
         case NC_UINT:
-            return ncmpix_pad_putn_$1_uint  (xpp, nelems, (uint*)tp);
+            return ncmpix_getn_NC_UINT_$1  (&xp, nelems, buf);
         case NC_FLOAT:
-            return ncmpix_pad_putn_$1_float (xpp, nelems, (float*)tp);
+            return ncmpix_getn_NC_FLOAT_$1 (&xp, nelems, buf);
         case NC_DOUBLE:
-            return ncmpix_pad_putn_$1_double(xpp, nelems, (double*)tp);
+            return ncmpix_getn_NC_DOUBLE_$1(&xp, nelems, buf);
         case NC_INT64:
-            return ncmpix_pad_putn_$1_longlong (xpp, nelems, (longlong*)tp);
+            return ncmpix_getn_NC_INT64_$1 (&xp, nelems, buf);
         case NC_UINT64:
-            return ncmpix_pad_putn_$1_ulonglong(xpp, nelems, (ulonglong*)tp);
-        default: fprintf(stderr, "Error: bad btype(%d) in %s\n",btype,__func__);
+            return ncmpix_getn_NC_UINT64_$1(&xp, nelems, buf);
+        case NC_CHAR:
+            return NC_ECHAR; /* NC_ECHAR already checked earlier */
+        default:
+            fprintf(stderr, "Error: bad attrp->type(%d) in %s\n",
+                    attrp->type,__func__);
+            return NC_EBADTYPE;
     }
-    return NC_EBADTYPE;
 }
 ')dnl
 
-PAD_PUTN_FILETYPE(schar)
-PAD_PUTN_FILETYPE(uchar)
-PAD_PUTN_FILETYPE(short)
-PAD_PUTN_FILETYPE(ushort)
+foreach(`itype', (schar,uchar,short,ushort,int,uint,long,float,double,longlong,ulonglong),
+        `GET_ATT(itype)
+')
 
 dnl
-dnl PUTN_FILETYPE(ftype)
+dnl PUTN_ITYPE(_pad, itype)
 dnl
-define(`PUTN_FILETYPE',dnl
+define(`PUTN_ITYPE',dnl
 `dnl
 /*----< ncmpix_putn_$1() >---------------------------------------------------*/
+/* This is a collective subroutine */
 inline static int
-ncmpix_putn_$1(void       **xpp,
-               MPI_Offset   nelems,
-               const void  *tp,
-               nc_type      btype)
+ncmpix_putn_$1(void       **xpp,    /* buffer to be written to file */
+               MPI_Offset   nelems, /* no. elements in user buffer */
+               const $1    *buf,    /* user buffer of type $1 */
+               nc_type      xtype,  /* external NC type */
+               void        *fillp)  /* fill value in internal representation */
 {
-    switch(btype) {
-        case NC_CHAR:
+    switch(xtype) {
         case NC_BYTE:
-            return ncmpix_putn_$1_schar (xpp, nelems, (schar*)tp);
+            return ncmpix_pad_putn_NC_BYTE_$1  (xpp, nelems, buf, fillp);
         case NC_UBYTE:
-            return ncmpix_putn_$1_uchar (xpp, nelems, (uchar*)tp);
+            return ncmpix_pad_putn_NC_UBYTE_$1 (xpp, nelems, buf, fillp);
         case NC_SHORT:
-            return ncmpix_putn_$1_short (xpp, nelems, (short*)tp);
+            return ncmpix_pad_putn_NC_SHORT_$1 (xpp, nelems, buf, fillp);
         case NC_USHORT:
-            return ncmpix_putn_$1_ushort(xpp, nelems, (ushort*)tp);
+            return ncmpix_pad_putn_NC_USHORT_$1(xpp, nelems, buf, fillp);
         case NC_INT:
-            return ncmpix_putn_$1_int   (xpp, nelems, (int*)tp);
+            return ncmpix_putn_NC_INT_$1   (xpp, nelems, buf, fillp);
         case NC_UINT:
-            return ncmpix_putn_$1_uint  (xpp, nelems, (uint*)tp);
+            return ncmpix_putn_NC_UINT_$1  (xpp, nelems, buf, fillp);
         case NC_FLOAT:
-            return ncmpix_putn_$1_float (xpp, nelems, (float*)tp);
+            return ncmpix_putn_NC_FLOAT_$1 (xpp, nelems, buf, fillp);
         case NC_DOUBLE:
-            return ncmpix_putn_$1_double(xpp, nelems, (double*)tp);
+            return ncmpix_putn_NC_DOUBLE_$1(xpp, nelems, buf, fillp);
         case NC_INT64:
-            return ncmpix_putn_$1_longlong (xpp, nelems, (longlong*)tp);
+            return ncmpix_putn_NC_INT64_$1 (xpp, nelems, buf, fillp);
         case NC_UINT64:
-            return ncmpix_putn_$1_ulonglong(xpp, nelems, (ulonglong*)tp);
-        default: fprintf(stderr, "Error: bad btype(%d) in %s\n",btype,__func__);
+            return ncmpix_putn_NC_UINT64_$1(xpp, nelems, buf, fillp);
+        case NC_CHAR:
+            return NC_ECHAR; /* NC_ECHAR check is done earlier */
+        default: fprintf(stderr, "Error: bad xtype(%d) in %s\n",xtype,__func__);
+            return NC_EBADTYPE;
     }
-    return NC_EBADTYPE;
 }
 ')dnl
 
-PUTN_FILETYPE(int)
-PUTN_FILETYPE(uint)
-PUTN_FILETYPE(float)
-PUTN_FILETYPE(double)
-PUTN_FILETYPE(int64)
-PUTN_FILETYPE(uint64)
+foreach(`itype', (schar,uchar,short,ushort,int,uint,long,float,double,longlong,ulonglong),
+        `PUTN_ITYPE(itype)
+')
 
-/*----< ncmpix_pad_putn() >--------------------------------------------------*/
-/* padding only applicable to file types of size smaller than 4 bytes */
-inline static int
-ncmpix_pad_putn(void       **xpp,
-                MPI_Offset   nelems,
-                const void  *tp,
-                nc_type      filetype,
-                nc_type      buftype)
-{
-    /* put n elements from (buftype*)tp to (filetype*)*xpp */
-    /* Checking for character-number conversion should have been done */
 
-    switch(filetype) {
-        case NC_CHAR:
-        case NC_BYTE:
-            return ncmpix_pad_putn_schar (xpp, nelems, tp, buftype);
-        case NC_UBYTE:
-            return ncmpix_pad_putn_uchar (xpp, nelems, tp, buftype);
-        case NC_SHORT:
-            return ncmpix_pad_putn_short (xpp, nelems, tp, buftype);
-        case NC_USHORT:
-            return ncmpix_pad_putn_ushort(xpp, nelems, tp, buftype);
-        case NC_INT:
-            return ncmpix_putn_int       (xpp, nelems, tp, buftype);
-        case NC_UINT:
-            return ncmpix_putn_uint      (xpp, nelems, tp, buftype);
-        case NC_FLOAT:
-            return ncmpix_putn_float     (xpp, nelems, tp, buftype);
-        case NC_DOUBLE:
-            return ncmpix_putn_double    (xpp, nelems, tp, buftype);
-        case NC_INT64:
-            return ncmpix_putn_int64     (xpp, nelems, tp, buftype);
-        case NC_UINT64:
-            return ncmpix_putn_uint64    (xpp, nelems, tp, buftype);
-        default: fprintf(stderr, "Error: bad filetype(%d) in %s\n",filetype,__func__);
-    }
-    return NC_EBADTYPE;
-}
+/* For netCDF, the type mapping between file types and buffer types
+ * are based on netcdf4. Check APIs of nc_put_att_xxx from source files
+ *     netCDF/netcdf-x.x.x/libdispatch/att.c
+ *     netCDF/netcdf-x.x.x/libsrc4/nc4attr.c
+ *
+ * Note that schar means signed 1-byte integers in attributes. Hence the call
+ * below is illegal (NC_ECHAR will return), indicating the error on trying
+ * type conversion between characters and numbers.
+ *
+ * ncmpi_put_att_schar(ncid, varid, "attr name", NC_CHAR, strlen(attrp), attrp);
+ *
+ * This rule and mapping apply for variables as well. See APIs of
+ * nc_put_vara_xxx from source files
+ *     netCDF/netcdf-x.x.x/libdispatch/var.c
+ *     netCDF/netcdf-x.x.x/libsrc4/nc4var.c
+ *
+ */
 
-/*----< ncmpii_put_att() >---------------------------------------------------*/
-/* Note from netCDF user guide:
+dnl
+dnl PUT_ATT(fntype)
+dnl
+define(`PUT_ATT',dnl
+`dnl
+/*----< ncmpi_put_att_$1() >-------------------------------------------------*/
+/* This is a collective subroutine, all arguments should be consistent among
+ * all processes.
+ *
+ * Note from netCDF user guide:
  * Attributes are always single values or one-dimensional arrays. This works
  * out well for a string, which is a one-dimensional array of ASCII characters
  *
- * This PnetCDF API is collective if called in data mode.
+ * Note ncmpi_put_att_text will never return NC_ERANGE error, as text is not
+ * convertible to numerical types.
  */
-static int
-ncmpii_put_att(int         ncid,
-               int         varid,
-               const char *name,     /* attribute name */
-               nc_type     filetype, /* type defined in file header */
-               MPI_Offset  nelems,   /* number of elements of type buftype */
-               const void *buf,      /* I/O buffer */
-               nc_type     buftype)  /* I/O buffer type */
+int
+ncmpi_put_att_$1(int         ncid,
+                 int         varid,
+                 const char *name,     /* attribute name */
+                 ifelse(`$1',`text',,`nc_type xtype,')
+                 MPI_Offset  nelems,   /* number of elements in buf */
+                 const FUNC2ITYPE($1) *buf) /* user write buffer */
 {
-    int indx, file_ver, err, status=NC_NOERR, mpireturn;
+    int indx=0, err;
+    char *nname=NULL; /* normalized name */
+    MPI_Offset xsz=0;
     NC *ncp;
-    NC_attrarray *ncap;
-    NC_attr *attrp, *old=NULL;
+    NC_attrarray *ncap=NULL;
+    NC_attr *attrp=NULL;
+    ifelse(`$1',`text', `nc_type xtype=NC_CHAR;')
 
-    if (!name || strlen(name) > NC_MAX_NAME)
-        DEBUG_RETURN_ERROR(NC_EBADNAME)
+    /* get the pointer to NC object */
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
-    /* Should CDF-5 allow very large file header? */
-    /* if (len > X_INT_MAX) DEBUG_RETURN_ERROR(NC_EINVAL) */
+    /* file should be opened with writable permission */
+    if (NC_readonly(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EPERM)
+        goto err_check;
+    }
 
-    /* get the file ID */
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    /* check if varid is valid and get the pointer to the attribute array */
+    ncap = NC_attrarray0(ncp, varid);
+    if (ncap == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTVAR)
+        goto err_check;
+    }
 
-    /* file should be opened with writable permission */
-    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM)
+    /* Should CDF-5 allow very large file header? */
+    /*
+    if (len > X_INT_MAX) {
+        DEBUG_ASSIGN_ERROR(err, NC_EINVAL)
+        goto err_check;
+    }
+    */
 
     /* nelems can be zero, i.e. an attribute with only its name */
-    if (nelems > 0 && buf == NULL)
-        DEBUG_RETURN_ERROR(NC_EINVAL) /* Null arg */
+    if (nelems > 0 && buf == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_EINVAL) /* Null arg */
+        goto err_check;
+    }
+
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME) {
+        DEBUG_ASSIGN_ERROR(err, NC_EBADNAME)
+        goto err_check;
+    }
 
     /* If this is the _FillValue attribute, then let PnetCDF return the
      * same error codes as netCDF
      */
-    if (!strcmp(name, "_FillValue")) {
+    if (varid != NC_GLOBAL && !strcmp(name, "_FillValue")) {
         NC_var *varp;
-        status = ncmpii_NC_lookupvar(ncp, varid, &varp);
-        if (status != NC_NOERR) return status;
+        err = ncmpii_NC_lookupvar(ncp, varid, &varp);
+        if (err != NC_NOERR) {
+            DEBUG_TRACE_ERROR
+            goto err_check;
+        }
 
         /* Fill value must be same type and have exactly one value */
-        if (filetype != varp->type)
-            DEBUG_RETURN_ERROR(NC_EBADTYPE)
+        if (xtype != varp->type) {
+            DEBUG_ASSIGN_ERROR(err, NC_EBADTYPE)
+            goto err_check;
+        }
 
-        if (nelems != 1)
-            DEBUG_RETURN_ERROR(NC_EINVAL)
+        if (nelems != 1) {
+            DEBUG_ASSIGN_ERROR(err, NC_EINVAL)
+            goto err_check;
+        }
 
         /* enable the fill mode for this variable */
         varp->no_fill = 0;
     }
 
-    /* get the file format version */
-    file_ver = 1;
-    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
-        file_ver = 2;
-    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
-        file_ver = 5;
-
-    if (nelems < 0 || (nelems > X_INT_MAX && file_ver <= 2))
-        DEBUG_RETURN_ERROR(NC_EINVAL) /* Invalid nelems */
+    if (nelems < 0 || (nelems > X_INT_MAX && ncp->format <= 2)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EINVAL) /* Invalid nelems */
+        goto err_check;
+    }
 
-    /* check if filetype is valid, as filetype is given by user
-     * no need to check buftype, as buftype is set internally
-     */
-    status = ncmpii_cktype(file_ver, filetype);
-    if (status != NC_NOERR) return status;
+    ifelse(`$1',`text', ,`/* check if xtype is valid */
+    err = ncmpii_cktype(ncp->format, xtype);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }')
 
-    /* No character conversions are allowed. */
-    if (filetype != buftype &&
-        (filetype == NC_CHAR || buftype == NC_CHAR))
-        DEBUG_RETURN_ERROR(NC_ECHAR)
+    ifelse(`$1',`text', , `/* No character conversions are allowed. */
+    if (xtype == NC_CHAR) {
+        DEBUG_ASSIGN_ERROR(err, NC_ECHAR)
+        goto err_check;
+    }')
 
     /* check if the attribute name is legal */
-    status = ncmpii_NC_check_name(name, file_ver);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_name(name, ncp->format);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
 
-    /* get the pointer to the attribute array */
-    ncap = NC_attrarray0(ncp, varid);
-    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+    xsz = ncmpix_len_NC_attrV(xtype, nelems);
+    /* xsz is the total size of this attribute */
 
-    indx = ncmpii_NC_findattr(ncap, name);
-    if (indx >= 0) { /* name in use */
-        if (!NC_indef(ncp)) {
-            /* in data mode, meaning to over-write an existing attribute
-             * if called in data mode (collective or independent), this
-             * function must be called collectively, i.e. all processes must
-             * participate
-             */
+    if (xsz != (int)xsz) {
+        DEBUG_ASSIGN_ERROR(err, NC_EINTOVERFLOW)
+        goto err_check;
+    }
 
-            const MPI_Offset xsz = ncmpix_len_NC_attrV(filetype, nelems);
-            /* xsz is the total size of this attribute */
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
+    }
 
-            attrp = ncap->value[indx]; /* convenience */
+    /* check whether attribute already exists */
+    indx = ncmpii_NC_findattr(ncap, nname);
 
-            if (xsz > attrp->xsz) /* new attribute requires a larger space */
-                DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
-            /* else, we can reuse existing without redef */
+    if (indx >= 0) { /* name in use */
+        /* xsz is the total size of this attribute */
+        if (!NC_indef(ncp) && xsz > ncap->value[indx]->xsz) {
+            /* new attribute requires a larger space, not allowed in data mode */
+            DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+            goto err_check;
+        }
+    }
+    else { /* attribute does not exit in ncid */
+        if (!NC_indef(ncp)) { /* add new attribute is not allowed in data mode */
+            DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+            goto err_check;
+        }
+        if (ncap->ndefined >= NC_MAX_ATTRS) {
+            DEBUG_ASSIGN_ERROR(err, NC_EMAXATTS)
+            goto err_check;
+        }
+    }
 
-            if (xsz != (int)xsz) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+err_check:
+    if (ncp->safe_mode) { /* consistency check */
+        int rank, root_varid, status, mpireturn;
+        char root_name[NC_MAX_NAME];
+        MPI_Offset root_nelems;
+        size_t buf_size;
+        void *root_buf;
+        ifelse(`$1',`text',,`int root_xtype;')
+
+        /* check if name is consistent among all processes */
+        if (name == NULL || *name == 0)
+            root_name[0] = 0;
+        else
+            strncpy(root_name, name, NC_MAX_NAME);
+        TRACE_COMM(MPI_Bcast)(root_name, NC_MAX_NAME, MPI_CHAR, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && strcmp(root_name, name))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_NAME)
+
+        /* check if varid is consistent across all processes */
+        root_varid = varid;
+        TRACE_COMM(MPI_Bcast)(&root_varid, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && root_varid != varid)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FNC_ARGS)
+
+        /* check if nelems is consistent across all processes */
+        root_nelems = nelems;
+        TRACE_COMM(MPI_Bcast)(&root_nelems, 1, MPI_OFFSET, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && root_nelems != nelems)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_LEN)
+
+        ifelse(`$1',`text', , `root_xtype = xtype;
+        TRACE_COMM(MPI_Bcast)(&root_xtype, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && root_xtype != xtype)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_TYPE)')
+
+        /* check if buf contents is consistent across all processes */
+        /* note xsz is aligned, thus must use the exact size of buf */
+        buf_size = (size_t)root_nelems * sizeof(FUNC2ITYPE($1));
+        MPI_Comm_rank(ncp->nciop->comm, &rank);
+        if (rank > 0)
+            root_buf = (void*) NCI_Malloc(buf_size);
+        else
+            root_buf = (void*)buf;
+        TRACE_COMM(MPI_Bcast)(root_buf, (int)buf_size, MPI_BYTE, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && (root_nelems != nelems || memcmp(root_buf, buf, buf_size)))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+        if (rank > 0) NCI_Free(root_buf);
+
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        }
 
-            attrp->xsz = xsz;
-            attrp->type = filetype;
-            attrp->nelems = nelems;
+        if (err == NC_NOERR) err = status;
+    }
+
+    if (err != NC_NOERR) {
+        if (nname != NULL) free(nname);
+        return err;
+    }
+    assert(ncap != NULL);
+    assert(nname != NULL);
+
+    if (indx >= 0) { /* name in use */
+        attrp = ncap->value[indx]; /* convenience */
 
-            if (nelems != 0) {
-                void *xp = attrp->xvalue;
-                /* using xp to prevent change the pointer attr->xvalue,
-                 * as ncmpix_pad_putn() advances the first argument
-                 * with nelems elements
-                 */
-                status = ncmpix_pad_putn(&xp, nelems, buf, filetype, buftype);
-                /* wkliao: why not return here if status != NC_NOERR? */
-
-                /* PnetCDF expects all processes use the same argument values.
-                 * However, when argument values are not the same, only root's
-                 * value is significant. Broadcast the new attribute at root to
-                 * overwrite new attribute at other processes.
-                 */
-                TRACE_COMM(MPI_Bcast)(attrp->xvalue, (int)attrp->xsz, MPI_BYTE,
-                                      0, ncp->nciop->comm);
-                if (mpireturn != MPI_SUCCESS) {
-                    err = ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
-                    if (status == NC_NOERR) status = err;
-                }
-            }
-
-            /* Let root write the entire header to the file. Note that we
-             * cannot just update the attribute in its space occupied in the
-             * file header, because if the file space occupied by the attribute
-             * shrinks, all the metadata following it must be moved ahead.
+        if (xsz > attrp->xsz) { /* new attribute requires a larger space */
+            /* Note the whole attribute object is allocated as one contiguous
+             * chunk, so we cannot realloc attrp->xvalue only
              */
-            err = ncmpii_write_header(ncp);
-            return (status == NC_NOERR) ? err : status;
+            ncmpii_free_NC_attr(attrp);
+            attrp = ncmpii_new_NC_attr(nname, xtype, nelems);
+            free(nname);
+            if (attrp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+            ncap->value[indx] = attrp;
+        }
+        else {
+            free(nname);
+            attrp->xsz    = xsz;
+            attrp->type   = xtype;
+            attrp->nelems = nelems;
         }
-        /* else, redefine using existing array slot */
-        old = ncap->value[indx];
     }
-    else { /* name never been used */
-        /* creating new attributes must be done in define mode */
-        if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+    else { /* attribute does not exit in ncid */
+        attrp = ncmpii_new_NC_attr(nname, xtype, nelems);
+        free(nname);
+        if (attrp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
 
-        if (ncap->ndefined >= NC_MAX_ATTRS)
-            DEBUG_RETURN_ERROR(NC_EMAXATTS)
+        err = incr_NC_attrarray(ncap, attrp);
+        if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
     }
 
-    /* create a new attribute object */
-    attrp = ncmpii_new_NC_attr(name, filetype, nelems);
-    if (attrp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
-
-    if (nelems != 0) { /* non-zero length attribute */
+    if (nelems != 0 && buf != NULL) { /* non-zero length attribute */
+        /* using xp below to prevent change the pointer attr->xvalue, as
+         * ncmpix_pad_putn_<type>() advances the first argument with nelems
+         * elements
+         */
         void *xp = attrp->xvalue;
-        status = ncmpix_pad_putn(&xp, nelems, buf, filetype, buftype);
-        /* wkliao: no immediately return error code here? Strange ... 
-         *         Instead, we continue and call incr_NC_attrarray() to add
-         *         this attribute (for create case) as it is legal. But if
-         *         we return error and reject this attribute, then nc_test will
-         *         fail with this error message below:
-         *         FAILURE at line 252 of test_read.c: ncmpi_inq: wrong number
-         *         of global atts returned, 3
-         *         Check netCDF-4, it is doing the same thing!
+        unsigned char fill[8]; /* fill value in internal representation */
+
+        /* find the fill value */
+        err = ncmpii_inq_default_fill_value(xtype, &fill);
+        if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+
+        ifelse(`$1',`text', `err = ncmpix_pad_putn_text(&xp, nelems, buf);',
+               `$1',`uchar',`
+        if (ncp->format < 5 && xtype == NC_BYTE) { /* no NC_ERANGE check */
+            err = ncmpii_inq_default_fill_value(NC_UBYTE, &fill);
+            if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+            err = ncmpix_putn_uchar(&xp, nelems, buf, NC_UBYTE, &fill);
+        } else
+            err = ncmpix_putn_$1(&xp, nelems, buf, xtype, &fill);',
+        `err = ncmpix_putn_$1(&xp, nelems, buf, xtype, &fill);')
+
+        /* no immediately return error code here? Strange ... 
+         * Instead, we continue and call incr_NC_attrarray() to add
+         * this attribute (for create case) as it is legal. But if
+         * we return error and reject this attribute, then nc_test will
+         * fail with this error message below:
+         * FAILURE at line 252 of test_read.c: ncmpi_inq: wrong number
+         * of global atts returned, 3
+         * Check netCDF-4, it is doing the same thing!
          *
-         *         One of the error codes returned from ncmpix_pad_putn() is
-         *         NC_ERANGE, meaning one or more elements are type overflow.
-         *         Should we reject the entire attribute array if only part of
-         *         the array overflow? For netCDF4, the answer is NO.
+         * One of the error codes returned from ncmpix_pad_putn_<type>() is
+         * NC_ERANGE, meaning one or more elements are type overflow.
+         * Should we reject the entire attribute array if only part of
+         * the array overflow? For netCDF4, the answer is NO.
          */ 
 /*
-        if (status != NC_NOERR) {
+        if (err != NC_NOERR) {
             ncmpii_free_NC_attr(attrp);
-            return status;
+            DEBUG_RETURN_ERROR(err)
         }
 */
     }
 
-    if (indx >= 0) { /* modify the existing attribute */
-        assert(old != NULL);
-        ncap->value[indx] = attrp;
-        ncmpii_free_NC_attr(old);
-    }
-    else { /* creating a new attribute */
-        err = incr_NC_attrarray(ncap, attrp);
-        if (err != NC_NOERR) {
-            ncmpii_free_NC_attr(attrp);
-            return err;
-        }
+    if (!NC_indef(ncp)) { /* called in data mode */
+        /* Let root write the entire header to the file. Note that we
+         * cannot just update the attribute in its space occupied in the
+         * file header, because if the file space occupied by the attribute 
+         * shrinks, all the metadata following it must be moved ahead. 
+         */
+        int status;
+        status = ncmpii_write_header(ncp); /* update file header */
+        if (err == NC_NOERR) err = status;
     }
 
-    return status;
+    return err;
 }
+')dnl
+
+foreach(`itype', (text,schar,uchar,short,ushort,int,uint,long,float,double,longlong,ulonglong),
+        `PUT_ATT(itype)
+')
 
 /*----< ncmpi_put_att() >-----------------------------------------------------*/
+/* This is a collective subroutine, all arguments should be consistent among
+ * all processes.
+ *
+ * This API assumes user buffer data type matches the external type defined
+ * in file
+ */
 int
 ncmpi_put_att(int         ncid,
               int         varid,
               const char *name,
               nc_type     xtype,
               MPI_Offset  nelems,
-              const void *value)
-{
-    return ncmpii_put_att(ncid, varid, name, xtype, nelems, value, xtype);
-}
-
-/*----< ncmpi_put_att_text() >-----------------------------------------------*/
-int
-ncmpi_put_att_text(int ncid, int varid, const char *name,
-                   MPI_Offset nelems, const char *value)
-{
-    return ncmpii_put_att(ncid, varid, name, NC_CHAR,
-                          nelems, value, NC_CHAR);
-}
-
-dnl
-dnl PUT_ATT_TYPE(fntype, ext_buftype, nc_buftype)
-dnl
-define(`PUT_ATT_TYPE',dnl
-`dnl
-/*----< ncmpi_put_att_$1() >-------------------------------------------------*/
-int
-ncmpi_put_att_$1(int ncid, int varid, const char *name, nc_type xtype,
-                 MPI_Offset nelems, const $2 *value)
+              const void *buf)
 {
-    return ncmpii_put_att(ncid, varid, name, xtype, nelems, value, $3);
+    switch(xtype) {
+        case NC_CHAR:   return ncmpi_put_att_text     (ncid, varid, name,        nelems, buf);
+        case NC_BYTE:   return ncmpi_put_att_schar    (ncid, varid, name, xtype, nelems, buf);
+        case NC_UBYTE:  return ncmpi_put_att_uchar    (ncid, varid, name, xtype, nelems, buf);
+        case NC_SHORT:  return ncmpi_put_att_short    (ncid, varid, name, xtype, nelems, buf);
+        case NC_USHORT: return ncmpi_put_att_ushort   (ncid, varid, name, xtype, nelems, buf);
+        case NC_INT:    return ncmpi_put_att_int      (ncid, varid, name, xtype, nelems, buf);
+        case NC_UINT:   return ncmpi_put_att_uint     (ncid, varid, name, xtype, nelems, buf);
+        case NC_FLOAT:  return ncmpi_put_att_float    (ncid, varid, name, xtype, nelems, buf);
+        case NC_DOUBLE: return ncmpi_put_att_double   (ncid, varid, name, xtype, nelems, buf);
+        case NC_INT64:  return ncmpi_put_att_longlong (ncid, varid, name, xtype, nelems, buf);
+        case NC_UINT64: return ncmpi_put_att_ulonglong(ncid, varid, name, xtype, nelems, buf);
+        default: return NC_EBADTYPE;
+    }
 }
-')dnl
-
-PUT_ATT_TYPE(schar,     signed char,        NC_BYTE)
-PUT_ATT_TYPE(uchar,     unsigned char,      NC_UBYTE)
-PUT_ATT_TYPE(ubyte,     unsigned char,      NC_UBYTE)
-PUT_ATT_TYPE(short,     short,              NC_SHORT)
-PUT_ATT_TYPE(ushort,    unsigned short,     NC_USHORT)
-PUT_ATT_TYPE(int,       int,                NC_INT)
-PUT_ATT_TYPE(uint,      unsigned int,       NC_UINT)
-PUT_ATT_TYPE(long,      long,               longtype)
-PUT_ATT_TYPE(float,     float,              NC_FLOAT)
-PUT_ATT_TYPE(double,    double,             NC_DOUBLE)
-PUT_ATT_TYPE(longlong,  long long,          NC_INT64)
-PUT_ATT_TYPE(ulonglong, unsigned long long, NC_UINT64)
 
-/* For netCDF, the type mapping between file types and buffer types
- * are based on netcdf4. Check APIs of nc_put_att_xxx from source files
- *     netCDF/netcdf-4.1.3/libdispatch/att.c
- *     netCDF/netcdf-4.1.3/libsrc4/nc4attr.c
- *
- * Note that schar means signed 1-byte integers in attributes. Hence the call
- * below is illegal. NC_ECHAR will return, indicating the error on trying
- * type conversion between characters and numbers.
- *
- * ncmpi_put_att_schar(ncid, varid, "attr name", NC_CHAR, strlen(attrp), attrp);
- *
- * This rule and mapping apply for variables as well. See APIs of
- * nc_put_vara_xxx from source files
- *     netCDF/netcdf-4.1.3/libdispatch/var.c
- *     netCDF/netcdf-4.1.3/libsrc4/nc4var.c
- *
- */
diff --git a/src/lib/bput.m4 b/src/lib/bput.m4
index 3bdea38..2a1a62b 100644
--- a/src/lib/bput.m4
+++ b/src/lib/bput.m4
@@ -7,10 +7,10 @@ dnl
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: bput.m4 2320 2016-02-24 13:18:32Z wkliao $ */
+/* $Id: bput.m4 2559 2016-10-16 20:47:09Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -27,384 +27,6 @@ dnl
 #include "ncmpidtype.h"
 #include "macro.h"
 
-
-/*----< ncmpi_bput_var() >----------------------------------------------------*/
-int
-ncmpi_bput_var(int           ncid,
-               int           varid,
-               const void   *buf,
-               MPI_Offset    bufcount,
-               MPI_Datatype  buftype,
-               int          *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset *start, *count;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VAR,
-                                 0, 1, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
-
-    GET_FULL_DIMENSIONS(start, count)
-
-    /* bput_var is a special case of bput_varm */
-    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                                 (void*)buf, bufcount, buftype, reqid,
-                                 WRITE_REQ, 1, 0);
-    NCI_Free(start);
-    return status;
-}
-
-
-dnl
-dnl BPUT_VAR_TYPE(ncid, varid, op, reqid)
-dnl
-define(`BPUT_VAR_TYPE',dnl
-`dnl
-/*----< ncmpi_bput_var_$1() >-------------------------------------------------*/
-int
-ncmpi_bput_var_$1(int       ncid,
-                  int       varid,
-                  const $2 *op,
-                  int      *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset  *start, *count;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, API_VAR,
-                                 0, 0, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
-
-    GET_FULL_DIMENSIONS(start, count)
-
-    /* bput_var is a special case of bput_varm */
-    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                                 (void*)op, -1, $3, reqid, WRITE_REQ, 1, 0);
-    NCI_Free(start);
-    return status;
-}
-')dnl
-
-BPUT_VAR_TYPE(text,      char,               MPI_CHAR)
-BPUT_VAR_TYPE(schar,     schar,              MPI_SIGNED_CHAR)
-BPUT_VAR_TYPE(uchar,     uchar,              MPI_UNSIGNED_CHAR)
-BPUT_VAR_TYPE(short,     short,              MPI_SHORT)
-BPUT_VAR_TYPE(ushort,    ushort,             MPI_UNSIGNED_SHORT)
-BPUT_VAR_TYPE(int,       int,                MPI_INT)
-BPUT_VAR_TYPE(uint,      uint,               MPI_UNSIGNED)
-BPUT_VAR_TYPE(long,      long,               MPI_LONG)
-BPUT_VAR_TYPE(float,     float,              MPI_FLOAT)
-BPUT_VAR_TYPE(double,    double,             MPI_DOUBLE)
-BPUT_VAR_TYPE(longlong,  long long,          MPI_LONG_LONG_INT)
-BPUT_VAR_TYPE(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-
-/*----< ncmpi_bput_var1() >---------------------------------------------------*/
-int
-ncmpi_bput_var1(int               ncid,
-                int               varid,
-                const MPI_Offset *start,
-                const void       *buf,
-                MPI_Offset        bufcount,
-                MPI_Datatype      buftype,
-                int              *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset *count;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, NULL, bufcount, API_VAR1,
-                                 0, 1, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
-
-    GET_ONE_COUNT(count)
-
-    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                                 (void*)buf, bufcount, buftype, reqid,
-                                 WRITE_REQ, 1, 0);
-    NCI_Free(count);
-    return status;
-}
-
-dnl
-dnl BPUT_VAR1_TYPE(ncid, varid, start, op, reqid)
-dnl
-define(`BPUT_VAR1_TYPE',dnl
-`dnl
-/*----< ncmpi_bput_var1_$1() >------------------------------------------------*/
-int
-ncmpi_bput_var1_$1(int               ncid,
-                   int               varid,
-                   const MPI_Offset  start[],
-                   const $2         *op,
-                   int              *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset *count;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, NULL, 0, API_VAR1,
-                                 0, 0, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
-
-    GET_ONE_COUNT(count)
-
-    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                                 (void*)op, -1, $3, reqid, WRITE_REQ, 1, 0);
-    NCI_Free(count);
-    return status;
-}
-')dnl
-
-BPUT_VAR1_TYPE(text,      char,               MPI_CHAR)
-BPUT_VAR1_TYPE(schar,     schar,              MPI_SIGNED_CHAR)
-BPUT_VAR1_TYPE(uchar,     uchar,              MPI_UNSIGNED_CHAR)
-BPUT_VAR1_TYPE(short,     short,              MPI_SHORT)
-BPUT_VAR1_TYPE(ushort,    ushort,             MPI_UNSIGNED_SHORT)
-BPUT_VAR1_TYPE(int,       int,                MPI_INT)
-BPUT_VAR1_TYPE(uint,      uint,               MPI_UNSIGNED)
-BPUT_VAR1_TYPE(long,      long,               MPI_LONG)
-BPUT_VAR1_TYPE(float,     float,              MPI_FLOAT)
-BPUT_VAR1_TYPE(double,    double,             MPI_DOUBLE)
-BPUT_VAR1_TYPE(longlong,  long long,          MPI_LONG_LONG_INT)
-BPUT_VAR1_TYPE(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-
-/*----< ncmpi_bput_vara() >---------------------------------------------------*/
-int
-ncmpi_bput_vara(int               ncid,
-                int               varid,
-                const MPI_Offset *start,
-                const MPI_Offset *count,
-                const void       *buf,
-                MPI_Offset        bufcount,
-                MPI_Datatype      buftype,
-                int              *reqid)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARA,
-                                 0, 1, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                               (void*)buf, bufcount, buftype, reqid,
-                               WRITE_REQ, 1, 0);
-}
-
-dnl
-dnl BPUT_VARA_TYPE(ncid, varid, start, count, op, reqid)
-dnl
-define(`BPUT_VARA_TYPE',dnl
-`dnl
-/*----< ncmpi_bput_vara_$1() >------------------------------------------------*/
-int
-ncmpi_bput_vara_$1(int               ncid,
-                   int               varid,
-                   const MPI_Offset  start[],
-                   const MPI_Offset  count[],
-                   const $2         *op,
-                   int              *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARA,
-                                 0, 0, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                               (void*)op, -1, $3, reqid, WRITE_REQ, 1, 0);
-}
-')dnl
-
-BPUT_VARA_TYPE(text,      char,               MPI_CHAR)
-BPUT_VARA_TYPE(schar,     schar,              MPI_SIGNED_CHAR)
-BPUT_VARA_TYPE(uchar,     uchar,              MPI_UNSIGNED_CHAR)
-BPUT_VARA_TYPE(short,     short,              MPI_SHORT)
-BPUT_VARA_TYPE(ushort,    ushort,             MPI_UNSIGNED_SHORT)
-BPUT_VARA_TYPE(int,       int,                MPI_INT)
-BPUT_VARA_TYPE(uint,      uint,               MPI_UNSIGNED)
-BPUT_VARA_TYPE(long,      long,               MPI_LONG)
-BPUT_VARA_TYPE(float,     float,              MPI_FLOAT)
-BPUT_VARA_TYPE(double,    double,             MPI_DOUBLE)
-BPUT_VARA_TYPE(longlong,  long long,          MPI_LONG_LONG_INT)
-BPUT_VARA_TYPE(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-
-/*----< ncmpi_bput_vars() >---------------------------------------------------*/
-int
-ncmpi_bput_vars(int               ncid,
-                int               varid,
-                const MPI_Offset  start[],
-                const MPI_Offset  count[],
-                const MPI_Offset  stride[],
-                const void       *buf,
-                MPI_Offset        bufcount,
-                MPI_Datatype      buftype,
-                int              *reqid)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARS,
-                                 0, 1, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, stride, NULL,
-                               (void*)buf, bufcount, buftype, reqid,
-                               WRITE_REQ, 1, 0);
-}
-
-dnl
-dnl BPUT_VARS_TYPE(ncid, varid, start, count, stride, op, reqid)
-dnl
-define(`BPUT_VARS_TYPE',dnl
-`dnl
-/*----< ncmpi_bput_vars_$1() >------------------------------------------------*/
-int
-ncmpi_bput_vars_$1(int               ncid,
-                   int               varid,
-                   const MPI_Offset  start[],
-                   const MPI_Offset  count[],
-                   const MPI_Offset  stride[],
-                   const $2         *op,
-                   int              *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARS,
-                                 0, 0, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, stride, NULL,
-                               (void*)op, -1, $3, reqid, WRITE_REQ, 1, 0);
-}
-')dnl
-
-BPUT_VARS_TYPE(text,      char,               MPI_CHAR)
-BPUT_VARS_TYPE(schar,     schar,              MPI_SIGNED_CHAR)
-BPUT_VARS_TYPE(uchar,     uchar,              MPI_UNSIGNED_CHAR)
-BPUT_VARS_TYPE(short,     short,              MPI_SHORT)
-BPUT_VARS_TYPE(ushort,    ushort,             MPI_UNSIGNED_SHORT)
-BPUT_VARS_TYPE(int,       int,                MPI_INT)
-BPUT_VARS_TYPE(uint,      uint,               MPI_UNSIGNED)
-BPUT_VARS_TYPE(long,      long,               MPI_LONG)
-BPUT_VARS_TYPE(float,     float,              MPI_FLOAT)
-BPUT_VARS_TYPE(double,    double,             MPI_DOUBLE)
-BPUT_VARS_TYPE(longlong,  long long,          MPI_LONG_LONG_INT)
-BPUT_VARS_TYPE(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-/*----< ncmpi_bput_varm() >---------------------------------------------------*/
-int
-ncmpi_bput_varm(int               ncid,
-                int               varid,
-                const MPI_Offset  start[],
-                const MPI_Offset  count[],
-                const MPI_Offset  stride[],
-                const MPI_Offset  imap[],
-                const void       *buf,
-                MPI_Offset        bufcount,
-                MPI_Datatype      buftype,
-                int              *reqid)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARM,
-                                 0, 1, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, stride, imap,
-                               (void*)buf, bufcount, buftype, reqid,
-                               WRITE_REQ, 1, 0);
-}
-
-dnl
-dnl BPUT_VARM_TYPE(ncid, varid, start, count, stride, imap, op, reqid)
-dnl
-define(`BPUT_VARM_TYPE',dnl
-`dnl
-/*----< ncmpi_bput_varm_$1() >------------------------------------------------*/
-int
-ncmpi_bput_varm_$1(int               ncid,
-                   int               varid,
-                   const MPI_Offset  start[],
-                   const MPI_Offset  count[],
-                   const MPI_Offset  stride[],
-                   const MPI_Offset  imap[],
-                   const $2         *op,
-                   int              *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARM,
-                                 0, 0, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, stride, imap,
-                               (void*)op, -1, $3, reqid, WRITE_REQ, 1, 0);
-}
-')dnl
-
-BPUT_VARM_TYPE(text,      char,               MPI_CHAR)
-BPUT_VARM_TYPE(schar,     schar,              MPI_SIGNED_CHAR)
-BPUT_VARM_TYPE(uchar,     uchar,              MPI_UNSIGNED_CHAR)
-BPUT_VARM_TYPE(short,     short,              MPI_SHORT)
-BPUT_VARM_TYPE(ushort,    ushort,             MPI_UNSIGNED_SHORT)
-BPUT_VARM_TYPE(int,       int,                MPI_INT)
-BPUT_VARM_TYPE(uint,      uint,               MPI_UNSIGNED)
-BPUT_VARM_TYPE(long,      long,               MPI_LONG)
-BPUT_VARM_TYPE(float,     float,              MPI_FLOAT)
-BPUT_VARM_TYPE(double,    double,             MPI_DOUBLE)
-BPUT_VARM_TYPE(longlong,  long long,          MPI_LONG_LONG_INT)
-BPUT_VARM_TYPE(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-
 /*----< ncmpi_buffer_attach() >-----------------------------------------------*/
 int
 ncmpi_buffer_attach(int        ncid,
@@ -440,9 +62,8 @@ ncmpi_buffer_attach(int        ncid,
 int
 ncmpi_buffer_detach(int ncid)
 {
-    int     status;
-    NC     *ncp;
-    NC_req *cur_req;
+    int  i, status;
+    NC  *ncp;
 
     status = ncmpii_NC_check_id(ncid, &ncp);
     if (status != NC_NOERR) return status;
@@ -451,12 +72,10 @@ ncmpi_buffer_detach(int ncid)
     if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
 
     /* this API assumes users are responsible for no pending bput */
-    cur_req = ncp->head;
-    while (cur_req != NULL) { /* check if there is a pending bput */
-        if (cur_req->abuf_index >= 0)
+    for (i=0; i<ncp->numPutReqs; i++) {
+        if (ncp->put_list[i].abuf_index >= 0) /* check for a pending bput */
             DEBUG_RETURN_ERROR(NC_EPENDINGBPUT)
             /* return now, so users can call wait and try detach again */
-        cur_req = cur_req->next;
     }
 
     NCI_Free(ncp->abuf->buf);
@@ -478,9 +97,8 @@ ncmpi_buffer_detach(int         ncid,
                     void       *bufptr,
                     MPI_Offset *bufsize)
 {
-    int     status;
-    NC     *ncp;
-    NC_req *cur_req;
+    int  i, status;
+    NC  *ncp;
 
     status = ncmpii_NC_check_id(ncid, &ncp);
     if (status != NC_NOERR) return status;
@@ -493,11 +111,10 @@ ncmpi_buffer_detach(int         ncid,
     *bufsize         = ncp->abuf->size_allocated;
 
     /* this API assumes users are responsible for no pending bput when called */
-    cur_req = ncp->head;
-    while (cur_req != NULL) { /* check if there is a pending bput */
-        if (cur_req->abuf_index >= 0)
+    for (i=0; i<ncp->numPutReqs; i++) {
+        if (ncp->put_list[i].abuf_index >= 0) /* check for a pending bput */
             DEBUG_RETURN_ERROR(NC_EPENDINGBPUT)
-        cur_req = cur_req->next;
+            /* return now, so users can call wait and try detach again */
     }
 
     NCI_Free(ncp->abuf->occupy_table);
@@ -549,3 +166,56 @@ ncmpi_inq_buffer_size(int         ncid,
     return NC_NOERR;
 }
 
+include(`foreach.m4')dnl
+include(`utils.m4')dnl
+dnl
+define(`APINAME',`ifelse(`$2',`',`ncmpi_bput_var$1',`ncmpi_bput_var$1_$2')')dnl
+dnl
+dnl BPUT_API(kind, itype)
+dnl
+define(`BPUT_API',dnl
+`dnl
+/*----< APINAME($1,$2)() >------------------------------------------------*/
+int
+APINAME($1,$2)(int ncid, int varid, ArgKind($1) BufArgs(`put',$2), int *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    ifelse(`$1', `',  `MPI_Offset *start, *count;',
+           `$1', `1', `MPI_Offset *count;')
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, ArgStartCount($1),
+                                 ifelse(`$2', `', `bufcount', `0'),
+                                 ifelse(`$2', `', `buftype',  `ITYPE2MPI($2)'),
+                                 API_KIND($1), ifelse(`$2', `', `1', `0'),
+                                 0, WRITE_REQ,
+                                 NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    ifelse(`$1', `',  `GET_FULL_DIMENSIONS(start, count)',
+           `$1', `1', `GET_ONE_COUNT(count)')
+
+    /* APINAME($1,$2) is a special case of APINAME(m,$2) */
+    status = ncmpii_igetput_varm(ncp, varp, start, count, ArgStrideMap($1),
+                                 (void*)buf,
+                                 ifelse(`$2', `', `bufcount, buftype',
+                                                  `-1, ITYPE2MPI($2)'),
+                                 reqid, WRITE_REQ, 1, 0);
+    ifelse(`$1', `', `NCI_Free(start);', `$1', `1', `NCI_Free(count);')
+    return status;
+}
+')dnl
+dnl
+/*---- PnetCDF flexible APIs ------------------------------------------------*/
+foreach(`kind', (, 1, a, s, m),`BPUT_API(kind,)
+')
+
+/*---- PnetCDF high-level APIs ----------------------------------------------*/
+foreach(`kind', (, 1, a, s, m),
+        `foreach(`itype', (ITYPE_LIST),
+                 `BPUT_API(kind,itype)'
+)')
diff --git a/src/lib/convert_swap.m4 b/src/lib/convert_swap.m4
index 25792f1..c2ec6f7 100644
--- a/src/lib/convert_swap.m4
+++ b/src/lib/convert_swap.m4
@@ -7,10 +7,10 @@ dnl
  *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: convert_swap.m4 2290 2016-01-02 18:37:46Z wkliao $ */
+/* $Id: convert_swap.m4 2589 2016-10-30 17:42:43Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -18,8 +18,12 @@ dnl
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h> /* uint16_t, uint32_t, uint64_t */
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>   /* uint16_t, uint32_t, uint64_t */
+#endif
 #include <assert.h>
-#include <arpa/inet.h>   /* htonl(), htons() */
 
 #include <mpi.h>
 
@@ -27,11 +31,6 @@ dnl
 #include "ncx.h"
 #include "macro.h"
 
-/* Prototypes for functions used only in this file */
-#if 0
-static void swapn(void *dst, const void *src, MPI_Offset nn, int xsize);
-#endif
-
 /*
  *  Datatype Mapping:
  *
@@ -56,9 +55,9 @@ static void swapn(void *dst, const void *src, MPI_Offset nn, int xsize);
  */
 
 inline MPI_Datatype
-ncmpii_nc2mpitype(nc_type type)
+ncmpii_nc2mpitype(nc_type xtype)
 {
-    switch(type){
+    switch(xtype){
         case NC_BYTE :   return MPI_SIGNED_CHAR;
         case NC_CHAR :   return MPI_CHAR;
         case NC_SHORT :  return MPI_SHORT;
@@ -74,74 +73,88 @@ ncmpii_nc2mpitype(nc_type type)
     }
 }
 
+inline nc_type
+ncmpii_mpi2nctype(MPI_Datatype itype)
+{
+    if (itype == MPI_SIGNED_CHAR)        return NC_BYTE ;
+    if (itype == MPI_CHAR)               return NC_CHAR ;
+    if (itype == MPI_SHORT)              return NC_SHORT ;
+    if (itype == MPI_INT)                return NC_INT ;
+    if (itype == MPI_FLOAT)              return NC_FLOAT ;
+    if (itype == MPI_DOUBLE)             return NC_DOUBLE ;
+    if (itype == MPI_UNSIGNED_CHAR)      return NC_UBYTE ;
+    if (itype == MPI_UNSIGNED_SHORT)     return NC_USHORT ;
+    if (itype == MPI_UNSIGNED)           return NC_UINT ;
+    if (itype == MPI_LONG_LONG_INT)      return NC_INT64 ;
+    if (itype == MPI_UNSIGNED_LONG_LONG) return NC_UINT64 ;
+    return NC_EBADTYPE;
+}
+
 /*----< ncmpii_need_convert() >----------------------------------------------*/
-/* netCDF specification make a special case for type conversion between
- * uchar and scahr: do not check for range error. See
- * http://www.unidata.ucar.edu/software/netcdf/docs_rc/data_type.html#type_conversion
+/* netCDF specification makes a special case for type conversion between
+ * uchar and NC_BYTE: do not check for range error. See
+ * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
  */
 inline int
-ncmpii_need_convert(nc_type nctype,MPI_Datatype mpitype) {
-    return !( (nctype == NC_CHAR   && mpitype == MPI_CHAR)           ||
-              (nctype == NC_BYTE   && mpitype == MPI_SIGNED_CHAR)    ||
-              (nctype == NC_BYTE   && mpitype == MPI_UNSIGNED_CHAR)  ||
+ncmpii_need_convert(int          format, /* 1, 2, or 5 (CDF format number) */
+                    nc_type      xtype,  /* external NC type */
+                    MPI_Datatype itype)  /* internal MPI type */
+{
+
+    if (format > 2) { /* NC_BYTE is considered signed 1-byte integer */
+        if ((xtype == NC_BYTE  && itype == MPI_UNSIGNED_CHAR)
+#if defined(__CHAR_UNSIGNED__) && __CHAR_UNSIGNED__ != 0
+            || (xtype == NC_BYTE  && itype == MPI_CHAR)
+#endif
+           )
+       return 1;
+    }
+
+    return !( (xtype == NC_CHAR   && itype == MPI_CHAR)           ||
+              (xtype == NC_BYTE   && itype == MPI_SIGNED_CHAR)    ||
+              (xtype == NC_BYTE   && itype == MPI_UNSIGNED_CHAR)  ||
 #if defined(__CHAR_UNSIGNED__) && __CHAR_UNSIGNED__ != 0
-              (nctype == NC_BYTE   && mpitype == MPI_CHAR)           ||
+              (xtype == NC_BYTE   && itype == MPI_CHAR)           ||
 #endif
-              (nctype == NC_SHORT  && mpitype == MPI_SHORT)          ||
-              (nctype == NC_INT    && mpitype == MPI_INT)            ||
-              (nctype == NC_INT    && mpitype == MPI_LONG &&
-               X_SIZEOF_INT == SIZEOF_LONG)                          ||
-              (nctype == NC_FLOAT  && mpitype == MPI_FLOAT)          ||
-              (nctype == NC_DOUBLE && mpitype == MPI_DOUBLE)         ||
-              (nctype == NC_UBYTE  && mpitype == MPI_UNSIGNED_CHAR)  ||
-              (nctype == NC_USHORT && mpitype == MPI_UNSIGNED_SHORT) ||
-              (nctype == NC_UINT   && mpitype == MPI_UNSIGNED)       ||
-              (nctype == NC_INT64  && mpitype == MPI_LONG_LONG_INT)  ||
-              (nctype == NC_UINT64 && mpitype == MPI_UNSIGNED_LONG_LONG)
+              (xtype == NC_SHORT  && itype == MPI_SHORT)          ||
+              (xtype == NC_INT    && itype == MPI_INT)            ||
+              (xtype == NC_INT    && itype == MPI_LONG &&
+               X_SIZEOF_INT == SIZEOF_LONG)                       ||
+              (xtype == NC_FLOAT  && itype == MPI_FLOAT)          ||
+              (xtype == NC_DOUBLE && itype == MPI_DOUBLE)         ||
+              (xtype == NC_UBYTE  && itype == MPI_UNSIGNED_CHAR)  ||
+#if defined(__CHAR_UNSIGNED__) && __CHAR_UNSIGNED__ != 0
+              (xtype == NC_UBYTE  && itype == MPI_CHAR)           ||
+#endif
+              (xtype == NC_USHORT && itype == MPI_UNSIGNED_SHORT) ||
+              (xtype == NC_UINT   && itype == MPI_UNSIGNED)       ||
+              (xtype == NC_INT64  && itype == MPI_LONG_LONG_INT)  ||
+              (xtype == NC_UINT64 && itype == MPI_UNSIGNED_LONG_LONG)
             );
 }
 
 /*----< ncmpii_need_swap() >-------------------------------------------------*/
 inline int
-ncmpii_need_swap(nc_type      nctype,
-                 MPI_Datatype mpitype)
+ncmpii_need_swap(nc_type      xtype,  /* external NC type */
+                 MPI_Datatype itype)  /* internal MPI type */
 {
 #ifdef WORDS_BIGENDIAN
     return 0;
 #else
-    if ((nctype == NC_CHAR   && mpitype == MPI_CHAR)           ||
-        (nctype == NC_BYTE   && mpitype == MPI_SIGNED_CHAR)    ||
-        (nctype == NC_UBYTE  && mpitype == MPI_UNSIGNED_CHAR))
+    if ((xtype == NC_CHAR  && itype == MPI_CHAR)           ||
+        (xtype == NC_BYTE  && itype == MPI_SIGNED_CHAR)    ||
+        (xtype == NC_UBYTE && itype == MPI_UNSIGNED_CHAR))
         return 0;
 
     return 1;
 #endif
 }
 
-#if 0
-/*----< swapn() >------------------------------------------------------------*/
-inline static void
-swapn(void       *dst,
-      const void *src,
-      MPI_Offset  nn,
-      int         xsize)
-{
-    int i;
-    uchar *op = dst;
-    const uchar *ip = src;
-    while (nn-- != 0) {
-        for (i=0; i<xsize; i++)
-            op[i] = ip[xsize-1-i];
-        op += xsize;
-        ip += xsize;
-    }
-}
-#endif
-
 /* Endianness byte swap: done in-place */
 #define SWAP(x,y) {tmp = (x); (x) = (y); (y) = tmp;}
 
 /*----< ncmpii_swap() >-------------------------------------------------------*/
+/* out-place byte swap, i.e. dest_p != src_p */
 void
 ncmpii_swapn(void       *dest_p,  /* destination array */
              const void *src_p,   /* source array */
@@ -155,14 +168,37 @@ ncmpii_swapn(void       *dest_p,  /* destination array */
     if (esize == 4) { /* this is the most common case */
               uint32_t *dest = (uint32_t*)       dest_p;
         const uint32_t *src  = (const uint32_t*) src_p;
-        for (i=0; i<nelems; i++)
-            dest[i] = htonl(src[i]);
+        for (i=0; i<nelems; i++) {
+            dest[i] = src[i];
+            dest[i] =  ((dest[i]) << 24)
+                    | (((dest[i]) & 0x0000ff00) << 8)
+                    | (((dest[i]) & 0x00ff0000) >> 8)
+                    | (((dest[i]) >> 24));
+        }
+    }
+    else if (esize == 8) {
+              uint64_t *dest = (uint64_t*)       dest_p;
+        const uint64_t *src  = (const uint64_t*) src_p;
+        for (i=0; i<nelems; i++) {
+            dest[i] = src[i];
+            dest[i] = ((dest[i] & 0x00000000000000FFULL) << 56) | 
+                      ((dest[i] & 0x000000000000FF00ULL) << 40) | 
+                      ((dest[i] & 0x0000000000FF0000ULL) << 24) | 
+                      ((dest[i] & 0x00000000FF000000ULL) <<  8) | 
+                      ((dest[i] & 0x000000FF00000000ULL) >>  8) | 
+                      ((dest[i] & 0x0000FF0000000000ULL) >> 24) | 
+                      ((dest[i] & 0x00FF000000000000ULL) >> 40) | 
+                      ((dest[i] & 0xFF00000000000000ULL) >> 56);
+        }
     }
     else if (esize == 2) {
               uint16_t *dest =       (uint16_t*) dest_p;
         const uint16_t *src  = (const uint16_t*) src_p;
-        for (i=0; i<nelems; i++)
-            dest[i] = htons(src[i]);
+        for (i=0; i<nelems; i++) {
+            dest[i] = src[i];
+            dest[i] = (uint16_t)(((dest[i] & 0xff) << 8) |
+                                 ((dest[i] >> 8) & 0xff));
+        }
     }
     else {
               uchar *op = (uchar*) dest_p;
@@ -177,28 +213,62 @@ ncmpii_swapn(void       *dest_p,  /* destination array */
     }
 }
 
+/* Other options to in-place byte-swap
+htonl() is for 4-byte swap
+htons() is for 2-byte swap
+
+#include <arpa/inet.h>
+    dest[i] = htonl(dest[i]);
+    dest[i] = htons(dest[i]);
+
+Or
+
+#include <byteswap.h>
+
+        for (i=0; i<nelems; i++)
+            dest[i] = __bswap_32(dest[i]);
+
+*/
+
 /*----< ncmpii_in_swap() >---------------------------------------------------*/
+/* in-place byte swap */
 void
 ncmpii_in_swapn(void       *buf,
                 MPI_Offset  nelems,  /* number of elements in buf[] */
                 int         esize)   /* byte size of each element */
 {
-    int  i;
-    uchar tmp, *op = (uchar*)buf;
+    int i;
 
     if (esize <= 1 || nelems <= 0) return;  /* no need */
 
     if (esize == 4) { /* this is the most common case */
         uint32_t *dest = (uint32_t*) buf;
         for (i=0; i<nelems; i++)
-            dest[i] = htonl(dest[i]);
+            dest[i] =  ((dest[i]) << 24)
+                    | (((dest[i]) & 0x0000ff00) << 8)
+                    | (((dest[i]) & 0x00ff0000) >> 8)
+                    | (((dest[i]) >> 24));
+    }
+    else if (esize == 8) {
+        uint64_t *dest = (uint64_t*) buf;
+        for (i=0; i<nelems; i++)
+            dest[i] = ((dest[i] & 0x00000000000000FFULL) << 56) | 
+                      ((dest[i] & 0x000000000000FF00ULL) << 40) | 
+                      ((dest[i] & 0x0000000000FF0000ULL) << 24) | 
+                      ((dest[i] & 0x00000000FF000000ULL) <<  8) | 
+                      ((dest[i] & 0x000000FF00000000ULL) >>  8) | 
+                      ((dest[i] & 0x0000FF0000000000ULL) >> 24) | 
+                      ((dest[i] & 0x00FF000000000000ULL) >> 40) | 
+                      ((dest[i] & 0xFF00000000000000ULL) >> 56);
     }
     else if (esize == 2) {
         uint16_t *dest = (uint16_t*) buf;
         for (i=0; i<nelems; i++)
-            dest[i] = htons(dest[i]);
+            dest[i] = (uint16_t)(((dest[i] & 0xff) << 8) |
+                                 ((dest[i] >> 8) & 0xff));
     }
     else {
+        uchar tmp, *op = (uchar*)buf;
         /* for esize is not 1, 2, or 4 */
         while (nelems-- > 0) {
             for (i=0; i<esize/2; i++)
@@ -208,104 +278,128 @@ ncmpii_in_swapn(void       *buf,
     }
 }
 
-
 dnl
-dnl X_PUTN_FILETYPE(xtype)
+dnl PUTN_XTYPE(xtype)
 dnl
-define(`X_PUTN_FILETYPE',dnl
+define(`PUTN_XTYPE',dnl
 `dnl
 /*----< ncmpii_x_putn_$1() >--------------------------------------------------*/
 inline int
-ncmpii_x_putn_$1(void         *xp,      /* file buffer of type schar */
-                 const void   *putbuf,  /* put buffer of type puttype */
-                 MPI_Offset    nelems,
-                 MPI_Datatype  puttype)
+ncmpii_x_putn_$1(ifelse(`$1',`NC_BYTE',`int cdf_ver,/* 1,2,or 5 CDF format */')
+              void         *xp,     /* buffer of external type $1 */
+              const void   *buf,    /* user buffer of internal type, itype */
+              MPI_Offset    nelems,
+              MPI_Datatype  itype,  /* internal data type (MPI_Datatype) */
+              void         *fillp)  /* in internal representation */
 {
-    if (puttype == MPI_CHAR || /* assume ECHAR has been checked before */
-        puttype == MPI_SIGNED_CHAR)
-        return ncmpix_putn_$1_schar    (&xp, nelems, (const schar*)     putbuf);
-    else if (puttype == MPI_UNSIGNED_CHAR)
-        return ncmpix_putn_$1_uchar    (&xp, nelems, (const uchar*)     putbuf);
-    else if (puttype == MPI_SHORT)
-        return ncmpix_putn_$1_short    (&xp, nelems, (const short*)     putbuf);
-    else if (puttype == MPI_UNSIGNED_SHORT)
-        return ncmpix_putn_$1_ushort   (&xp, nelems, (const ushort*)    putbuf);
-    else if (puttype == MPI_INT)
-        return ncmpix_putn_$1_int      (&xp, nelems, (const int*)       putbuf);
-    else if (puttype == MPI_UNSIGNED)
-        return ncmpix_putn_$1_uint     (&xp, nelems, (const uint*)      putbuf);
-    else if (puttype == MPI_LONG)
-        return ncmpix_putn_$1_long     (&xp, nelems, (const long*)      putbuf);
-    else if (puttype == MPI_FLOAT)
-        return ncmpix_putn_$1_float    (&xp, nelems, (const float*)     putbuf);
-    else if (puttype == MPI_DOUBLE)
-        return ncmpix_putn_$1_double   (&xp, nelems, (const double*)    putbuf);
-    else if (puttype == MPI_LONG_LONG_INT)
-        return ncmpix_putn_$1_longlong (&xp, nelems, (const longlong*)  putbuf);
-    else if (puttype == MPI_UNSIGNED_LONG_LONG)
-        return ncmpix_putn_$1_ulonglong(&xp, nelems, (const ulonglong*) putbuf);
+    if (itype == MPI_CHAR || itype == MPI_SIGNED_CHAR)
+        /* This is for 1-byte integer, assuming ECHAR has been checked before */
+        return ncmpix_putn_$1_schar(&xp, nelems, (signed char*)buf, fillp);
+    else if (itype == MPI_UNSIGNED_CHAR) {
+        ifelse(`$1',`NC_BYTE',
+       `if (cdf_ver < 5)
+            return ncmpix_putn_NC_UBYTE_uchar(&xp, nelems,(const uchar*)buf, fillp);
+        else')
+            return ncmpix_putn_$1_uchar(&xp, nelems, (const uchar*)     buf, fillp);
+    }
+    else if (itype == MPI_SHORT)
+        return ncmpix_putn_$1_short    (&xp, nelems, (const short*)     buf, fillp);
+    else if (itype == MPI_UNSIGNED_SHORT)
+        return ncmpix_putn_$1_ushort   (&xp, nelems, (const ushort*)    buf, fillp);
+    else if (itype == MPI_INT)
+        return ncmpix_putn_$1_int      (&xp, nelems, (const int*)       buf, fillp);
+    else if (itype == MPI_UNSIGNED)
+        return ncmpix_putn_$1_uint     (&xp, nelems, (const uint*)      buf, fillp);
+    else if (itype == MPI_LONG)
+        return ncmpix_putn_$1_long     (&xp, nelems, (const long*)      buf, fillp);
+    else if (itype == MPI_FLOAT)
+        return ncmpix_putn_$1_float    (&xp, nelems, (const float*)     buf, fillp);
+    else if (itype == MPI_DOUBLE)
+        return ncmpix_putn_$1_double   (&xp, nelems, (const double*)    buf, fillp);
+    else if (itype == MPI_LONG_LONG_INT)
+        return ncmpix_putn_$1_longlong (&xp, nelems, (const longlong*)  buf, fillp);
+    else if (itype == MPI_UNSIGNED_LONG_LONG)
+        return ncmpix_putn_$1_ulonglong(&xp, nelems, (const ulonglong*) buf, fillp);
     DEBUG_RETURN_ERROR(NC_EBADTYPE)
 }
 ')dnl
 
-X_PUTN_FILETYPE(schar)
-X_PUTN_FILETYPE(uchar)
-X_PUTN_FILETYPE(short)
-X_PUTN_FILETYPE(ushort)
-X_PUTN_FILETYPE(int)
-X_PUTN_FILETYPE(uint)
-X_PUTN_FILETYPE(float)
-X_PUTN_FILETYPE(double)
-X_PUTN_FILETYPE(int64)
-X_PUTN_FILETYPE(uint64)
+PUTN_XTYPE(NC_UBYTE)
+PUTN_XTYPE(NC_SHORT)
+PUTN_XTYPE(NC_USHORT)
+PUTN_XTYPE(NC_INT)
+PUTN_XTYPE(NC_UINT)
+PUTN_XTYPE(NC_FLOAT)
+PUTN_XTYPE(NC_DOUBLE)
+PUTN_XTYPE(NC_INT64)
+PUTN_XTYPE(NC_UINT64)
+
+/* In CDF-2, NC_BYTE is considered a signed 1-byte integer in signed APIs, and
+ * unsigned 1-byte integer in unsigned APIs. In CDF-5, NC_BYTE is always a
+ * signed 1-byte integer. See
+ * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
+ */
+PUTN_XTYPE(NC_BYTE)
+
 
 dnl
-dnl X_GETN_FILETYPE(xtype)
+dnl GETN_XTYPE(xtype)
 dnl
-define(`X_GETN_FILETYPE',dnl
+define(`GETN_XTYPE',dnl
 `dnl
 /*----< ncmpii_x_getn_$1() >-------------------------------------------------*/
 inline int
-ncmpii_x_getn_$1(const void   *xp,      /* file buffer of type schar */
-                 void         *getbuf,  /* get buffer of type gettype */
-                 MPI_Offset    nelems,
-                 MPI_Datatype  gettype)
+ncmpii_x_getn_$1(ifelse(`$1',`NC_BYTE',`int cdf_ver,/* 1,2,or 5 CDF format */')
+              const void   *xp,     /* buffer of external type $1 */
+              void         *ip,     /* user buffer of internal type, itype */
+              MPI_Offset    nelems,
+              MPI_Datatype  itype)  /* internal data type (MPI_Datatype) */
 {
-    if (gettype == MPI_CHAR || /* assume ECHAR has been checked before */
-        gettype == MPI_SIGNED_CHAR)
-        return ncmpix_getn_$1_schar    (&xp, nelems, (schar*)     getbuf);
-    else if (gettype == MPI_UNSIGNED_CHAR)
-        return ncmpix_getn_$1_uchar    (&xp, nelems, (uchar*)     getbuf);
-    else if (gettype == MPI_SHORT)
-        return ncmpix_getn_$1_short    (&xp, nelems, (short*)     getbuf);
-    else if (gettype == MPI_UNSIGNED_SHORT)
-        return ncmpix_getn_$1_ushort   (&xp, nelems, (ushort*)    getbuf);
-    else if (gettype == MPI_INT)
-        return ncmpix_getn_$1_int      (&xp, nelems, (int*)       getbuf);
-    else if (gettype == MPI_UNSIGNED)
-        return ncmpix_getn_$1_uint     (&xp, nelems, (uint*)      getbuf);
-    else if (gettype == MPI_LONG)
-        return ncmpix_getn_$1_long     (&xp, nelems, (long*)      getbuf);
-    else if (gettype == MPI_FLOAT)
-        return ncmpix_getn_$1_float    (&xp, nelems, (float*)     getbuf);
-    else if (gettype == MPI_DOUBLE)
-        return ncmpix_getn_$1_double   (&xp, nelems, (double*)    getbuf);
-    else if (gettype == MPI_LONG_LONG_INT)
-        return ncmpix_getn_$1_longlong (&xp, nelems, (longlong*)  getbuf);
-    else if (gettype == MPI_UNSIGNED_LONG_LONG)
-        return ncmpix_getn_$1_ulonglong(&xp, nelems, (ulonglong*) getbuf);
+    if (itype == MPI_CHAR || itype == MPI_SIGNED_CHAR)
+        /* This is for 1-byte integer, assuming ECHAR has been checked before */
+        return ncmpix_getn_$1_schar(&xp, nelems, (signed char*)ip);
+    else if (itype == MPI_UNSIGNED_CHAR) {
+        ifelse(`$1',`NC_BYTE',`if (cdf_ver < 5)
+            return ncmpix_getn_NC_UBYTE_uchar(&xp, nelems,(uchar*)ip);
+        else')
+            return ncmpix_getn_$1_uchar(&xp, nelems,      (uchar*)ip);
+    }
+    else if (itype == MPI_SHORT)
+        return ncmpix_getn_$1_short    (&xp, nelems,      (short*)ip);
+    else if (itype == MPI_UNSIGNED_SHORT)
+        return ncmpix_getn_$1_ushort   (&xp, nelems,     (ushort*)ip);
+    else if (itype == MPI_INT)
+        return ncmpix_getn_$1_int      (&xp, nelems,        (int*)ip);
+    else if (itype == MPI_UNSIGNED)
+        return ncmpix_getn_$1_uint     (&xp, nelems,       (uint*)ip);
+    else if (itype == MPI_LONG)
+        return ncmpix_getn_$1_long     (&xp, nelems,       (long*)ip);
+    else if (itype == MPI_FLOAT)
+        return ncmpix_getn_$1_float    (&xp, nelems,      (float*)ip);
+    else if (itype == MPI_DOUBLE)
+        return ncmpix_getn_$1_double   (&xp, nelems,     (double*)ip);
+    else if (itype == MPI_LONG_LONG_INT)
+        return ncmpix_getn_$1_longlong (&xp, nelems,   (longlong*)ip);
+    else if (itype == MPI_UNSIGNED_LONG_LONG)
+        return ncmpix_getn_$1_ulonglong(&xp, nelems,  (ulonglong*)ip);
     DEBUG_RETURN_ERROR(NC_EBADTYPE)
 }
 ')dnl
 
-X_GETN_FILETYPE(schar)
-X_GETN_FILETYPE(uchar)
-X_GETN_FILETYPE(short)
-X_GETN_FILETYPE(ushort)
-X_GETN_FILETYPE(int)
-X_GETN_FILETYPE(uint)
-X_GETN_FILETYPE(float)
-X_GETN_FILETYPE(double)
-X_GETN_FILETYPE(int64)
-X_GETN_FILETYPE(uint64)
+GETN_XTYPE(NC_UBYTE)
+GETN_XTYPE(NC_SHORT)
+GETN_XTYPE(NC_USHORT)
+GETN_XTYPE(NC_INT)
+GETN_XTYPE(NC_UINT)
+GETN_XTYPE(NC_FLOAT)
+GETN_XTYPE(NC_DOUBLE)
+GETN_XTYPE(NC_INT64)
+GETN_XTYPE(NC_UINT64)
+
+/* In CDF-2, NC_BYTE is considered a signed 1-byte integer in signed APIs, and
+ * unsigned 1-byte integer in unsigned APIs. In CDF-5, NC_BYTE is always a
+ * signed 1-byte integer. See
+ * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
+ */
+GETN_XTYPE(NC_BYTE)
 
diff --git a/src/lib/depend b/src/lib/depend
index d07d4da..4679e00 100644
--- a/src/lib/depend
+++ b/src/lib/depend
@@ -29,3 +29,4 @@ subfile.o: subfile.c ncconfig.h subfile.h pnetcdf.h nc.h ncio.h fbits.h macro.h
 vard.o: vard.c ncconfig.h pnetcdf.h nc.h ncio.h fbits.h rnd.h ncx.h nctypes.h macro.h ncmpidtype.h
 fill.o: fill.c nc.h ncio.h pnetcdf.h fbits.h macro.h
 util.o: util.c nc.h ncio.h pnetcdf.h fbits.h macro.h
+hash_func.o: hash_func.c nc.h ncio.h pnetcdf.h fbits.h
diff --git a/src/lib/dim.c b/src/lib/dim.c
index 792f290..d67cfed 100644
--- a/src/lib/dim.c
+++ b/src/lib/dim.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: dim.c 2302 2016-01-10 20:33:45Z wkliao $ */
+/* $Id: dim.c 2588 2016-10-30 04:14:15Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #ifdef HAVE_STDLIB_H
@@ -56,36 +56,62 @@ ncmpii_new_x_NC_dim(NC_string *name)
 /*
  * Formerly, NC_new_dim(const char *name, long size)
  */
-static NC_dim *
-ncmpii_new_NC_dim(const char *uname,  /* dimension name */
-                  MPI_Offset  size)
+static int
+ncmpii_new_NC_dim(NC_dimarray  *ncap,
+                  const char   *name, /* normalized dim name */
+                  MPI_Offset    size,
+                  NC_dim      **dimp)
 {
     NC_string *strp;
-    NC_dim *dimp;
 
-    char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
-    if (name == NULL) return NULL;
+    if (strlen(name) == 0) DEBUG_RETURN_ERROR(NC_EBADNAME)
 
     strp = ncmpii_new_NC_string(strlen(name), name);
-    free(name);
-    if (strp == NULL) return NULL;
+    if (strp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
 
-    dimp = ncmpii_new_x_NC_dim(strp);
-    if (dimp == NULL) {
+    *dimp = ncmpii_new_x_NC_dim(strp);
+    if (*dimp == NULL) {
         ncmpii_free_NC_string(strp);
-        return NULL;
+        DEBUG_RETURN_ERROR(NC_ENOMEM)
     }
+    (*dimp)->size = size;
 
-    dimp->size = size;
+#ifndef SEARCH_NAME_LINEARLY
+    if (ncap != NULL) { /* insert new dim to hash table */
+        int key;
+        NC_nametable *nameT = ncap->nameT; /* dim name lookup table */
 
-    return(dimp);
-}
+        /* We use the first char as key for name lookup */
+        key = HASH_FUNC(name);
+
+        /* allocate or expand the space for nameT[key].list */
+        if (nameT[key].num % NC_NAME_TABLE_CHUNK == 0)
+            nameT[key].list = (int*) NCI_Realloc(nameT[key].list,
+                              (size_t)(nameT[key].num+NC_NAME_TABLE_CHUNK) * sizeof(int));
 
+        /* add the new variable ID to the name lookup table
+         * the new varid will be ncap->ndefined
+         */
+        nameT[key].list[nameT[key].num] = ncap->ndefined;
+        nameT[key].num++;
+    }
+    /* else case is for dimension duplication called from dup_NC_dim() */
+#endif
 
-NC_dim *
-dup_NC_dim(const NC_dim *dimp)
+    return NC_NOERR;
+}
+
+/*----< dup_NC_dim() >-------------------------------------------------------*/
+NC_dim*
+dup_NC_dim(const NC_dim *rdimp)
 {
-    return ncmpii_new_NC_dim(dimp->name->cp, dimp->size);
+    int err;
+    NC_dim *dimp;
+
+    /* rdimp->name->cp is a normalized string */
+    err = ncmpii_new_NC_dim(NULL, rdimp->name->cp, rdimp->size, &dimp);
+    if (err != NC_NOERR) return NULL;
+    return dimp;
 }
 
 /*----< ncmpii_find_NC_Udim() >----------------------------------------------*/
@@ -117,43 +143,67 @@ ncmpii_find_NC_Udim(const NC_dimarray  *ncap,
     return -1;
 }
 
-/*----< NC_finddim() >-------------------------------------------------------*/
+#ifdef SEARCH_NAME_LINEARLY
+/*----< ncmpii_NC_finddim() >------------------------------------------------*/
 /*
  * Step thru NC_DIMENSION array, seeking match on name.
- * Return dimid or -1 on not found.
- * *dimpp is set to the appropriate NC_dim.
+ * If found, set the dim ID pointed by dimidp, otherwise return NC_EBADDIM
  */
 static int
-NC_finddim(const NC_dimarray  *ncap,
-           const char         *uname,
-           NC_dim            **dimpp)
+ncmpii_NC_finddim(const NC_dimarray *ncap,
+                  const char        *name,  /* normalized dim name */
+                  int               *dimidp)
 {
     int dimid;
-    size_t nchars;
+    size_t nchars=strlen(name);
 
     assert(ncap != NULL);
 
-    if (ncap->ndefined == 0) return -1;
-
-    char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
-    nchars = strlen(name);
+    if (ncap->ndefined == 0) return NC_EBADDIM;
 
     /* note that the number of dimensions allowed is < 2^32 */
     for (dimid=0; dimid<ncap->ndefined; dimid++) {
         if (ncap->value[dimid]->name->nchars == nchars &&
             strncmp(ncap->value[dimid]->name->cp, name, nchars) == 0) {
             /* found the matched name */
-            if (dimpp != NULL)
-                *dimpp = ncap->value[dimid];
-            free(name);
-            return dimid;
+            if (dimidp != NULL) *dimidp = dimid;
+            return NC_NOERR; /* found it */
+        }
+    }
+    return NC_EBADDIM; /* the name is not found */
+}
+#else
+/*----< ncmpii_NC_finddim() >------------------------------------------------*/
+/*
+ * Search name from hash table ncap->nameT.
+ * If found, set the dim ID pointed by dimidp, otherwise return NC_EBADDIM
+ */
+static int
+ncmpii_NC_finddim(const NC_dimarray *ncap,
+                  const char        *name,  /* normalized dim name */
+                  int               *dimidp)
+{
+    int i, key, dimid;
+
+    assert(ncap != NULL);
+
+    if (ncap->ndefined == 0) return NC_EBADDIM;
+
+    /* hash the dim name into a key for name lookup */
+    key = HASH_FUNC(name);
+
+    /* check the list using linear search */
+    for (i=0; i<ncap->nameT[key].num; i++) {
+        dimid = ncap->nameT[key].list[i];
+        if (strcmp(name, ncap->value[dimid]->name->cp) == 0) {
+            if (dimidp != NULL) *dimidp = dimid;
+            return NC_NOERR; /* the name already exists */
         }
     }
-    free(name);
 
-    /* the name is not found */
-    return -1;
+    return NC_EBADDIM; /* the name has never been used */
 }
+#endif
 
 
 /* dimarray */
@@ -181,6 +231,13 @@ ncmpii_free_NC_dimarray(NC_dimarray *ncap)
     ncap->value    = NULL;
     ncap->nalloc   = 0;
     ncap->ndefined = 0;
+
+    /* free space allocated for dim name lookup table */
+    for (i=0; i<HASH_TABLE_SIZE; i++) {
+        if (ncap->nameT[i].num > 0)
+            NCI_Free(ncap->nameT[i].list);
+        ncap->nameT[i].num = 0;
+    }
 }
 
 
@@ -222,6 +279,17 @@ ncmpii_dup_NC_dimarray(NC_dimarray *ncap, const NC_dimarray *ref)
 
     ncap->ndefined = ref->ndefined;
 
+    /* duplicate dim name lookup table */
+    for (i=0; i<HASH_TABLE_SIZE; i++) {
+        ncap->nameT[i].num = ref->nameT[i].num;
+        ncap->nameT[i].list = NULL;
+        if (ncap->nameT[i].num > 0) {
+            ncap->nameT[i].list = NCI_Malloc((size_t)ncap->nameT[i].num * sizeof(int));
+            memcpy(ncap->nameT[i].list, ref->nameT[i].list,
+                   (size_t)ncap->nameT[i].num * sizeof(int));
+        }
+    }
+
     return NC_NOERR;
 }
 
@@ -292,78 +360,162 @@ ncmpi_def_dim(int         ncid,    /* IN:  file ID */
               MPI_Offset  size,    /* IN:  dimension size */
               int        *dimidp)  /* OUT: dimension ID */
 {
-    int dimid, file_ver, status;
-    NC *ncp;
-    NC_dim *dimp;
+    int dimid, err;
+    char *nname=NULL;  /* normalized name */
+    NC *ncp=NULL;
+    NC_dim *dimp=NULL;
 
     /* check if ncid is valid */
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
-    /* check if called in define mode */
-    if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+    /* must be called in define mode */
+    if (!NC_indef(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+        goto err_check;
+    }
 
-    /* check if the name string is legal for netcdf format */
-    file_ver = 1;
-    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
-        file_ver = 2;
-    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
-        file_ver = 5;
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME) {
+        DEBUG_ASSIGN_ERROR(err, NC_EBADNAME)
+        goto err_check;
+    }
 
-    status = ncmpii_NC_check_name(name, file_ver);
-    if (status != NC_NOERR) return status;
+    /* check if the name string is legal for the netcdf format */
+    err = ncmpii_NC_check_name(name, ncp->format);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
 
     /* MPI_Offset is usually a signed value, but serial netcdf uses
      * size_t -- normally unsigned
-     * In 1999 ISO C standard, size_t is a unsigned integer type of at least
+     * In 1999 ISO C standard, size_t is an unsigned integer type of at least
      * 16 bit. */
-    if ((ncp->flags & NC_64BIT_OFFSET) && SIZEOF_OFF_T > 4) {
-        /* CDF2 format and LFS, max is 2^32-4 */
+    if (ncp->format == 2) { /* CDF-2 format, max is 2^32-4 */
         if (size > X_UINT_MAX - 3 || (size < 0))
             /* "-3" handles rounded-up size */
-            DEBUG_RETURN_ERROR(NC_EDIMSIZE)
-    } else if ((ncp->flags & NC_64BIT_DATA)) {
-        /* CDF5 format*/
+            err = NC_EDIMSIZE;
+    } else if (ncp->format == 5) { /* CDF-5 format*/
         if (size < 0)
-            DEBUG_RETURN_ERROR(NC_EDIMSIZE)
-    } else {
-        /* CDF1 format, max is 2^31-4 */
+            err = NC_EDIMSIZE;
+    } else { /* CDF-1 format, max is 2^31-4 */
         if (size > X_INT_MAX - 3 || (size < 0))
             /* "-3" handles rounded-up size */
-            DEBUG_RETURN_ERROR(NC_EDIMSIZE)
+            err = NC_EDIMSIZE;
+    }
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
     }
 
     if (size == NC_UNLIMITED) {
+#if 0
         /* check for any existing unlimited dimension, netcdf allows
          * one per file
          */
         dimid = ncmpii_find_NC_Udim(&ncp->dims, &dimp);
-        if (dimid != -1) DEBUG_RETURN_ERROR(NC_EUNLIMIT) /* found an existing one */
+        if (dimid != -1) {
+            DEBUG_ASSIGN_ERROR(err, NC_EUNLIMIT) /* found an existing one */
+            goto err_check;
+        }
+#endif
+        if (ncp->dims.unlimited_id != -1) {
+            DEBUG_ASSIGN_ERROR(err, NC_EUNLIMIT) /* already defined */
+            goto err_check;
+        }
+    }
+
+    /* check if number of dimensions exceeds the upper bound */
+    if (ncp->dims.ndefined >= NC_MAX_DIMS) {
+        DEBUG_ASSIGN_ERROR(err, NC_EMAXDIMS)
+        goto err_check;
     }
 
-    /* check if exceeds the upperbound has reached */
-    if (ncp->dims.ndefined >= NC_MAX_DIMS) DEBUG_RETURN_ERROR(NC_EMAXDIMS)
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
+    }
 
     /* check if the name string is previously used */
-    dimid = NC_finddim(&ncp->dims, name, &dimp);
-    if (dimid != -1) DEBUG_RETURN_ERROR(NC_ENAMEINUSE)
+    err = ncmpii_NC_finddim(&ncp->dims, nname, NULL);
+    if (err != NC_EBADDIM) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENAMEINUSE)
+        goto err_check;
+    }
+    else
+        err = NC_NOERR;
+
+err_check:
+    if (ncp->safe_mode) {
+        int status, mpireturn;
+        char root_name[NC_MAX_NAME];
+        MPI_Offset root_size;
+
+        /* check if name is consistent among all processes */
+        if (name == NULL || *name == 0)
+            root_name[0] = 0;
+        else
+            strncpy(root_name, name, NC_MAX_NAME);
+        TRACE_COMM(MPI_Bcast)(root_name, NC_MAX_NAME, MPI_CHAR, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && strcmp(root_name, name))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_DIM_NAME)
+
+        /* check if sizes are consistent across all processes */
+        root_size = size;
+        TRACE_COMM(MPI_Bcast)(&root_size, 1, MPI_OFFSET, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && root_size != size)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_DIM_SIZE)
+
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        }
+        if (err == NC_NOERR) err = status;
+    }
+
+    if (err != NC_NOERR) {
+        if (nname != NULL) free(nname);
+        return err;
+    }
+
+    assert(nname != NULL);
 
     /* create a new dimension object */
-    dimp = ncmpii_new_NC_dim(name, size);
-    if (dimp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+    err = ncmpii_new_NC_dim(&ncp->dims, nname, size, &dimp);
+    free(nname);
+    if (err != NC_NOERR) {
+        if (dimp != NULL) ncmpii_free_NC_dim(dimp);
+        DEBUG_RETURN_ERROR(err)
+    }
 
-    /* Add a new handle to the end of an array of handles */
-    status = incr_NC_dimarray(&ncp->dims, dimp);
-    if (status != NC_NOERR) {
-        ncmpii_free_NC_dim(dimp);
-        return status;
+    /* Add a new dim handle to the end of handle array */
+    err = incr_NC_dimarray(&ncp->dims, dimp);
+    if (err != NC_NOERR) {
+        if (dimp != NULL) ncmpii_free_NC_dim(dimp);
+        DEBUG_RETURN_ERROR(err)
     }
 
-    if (dimidp != NULL)
-        *dimidp = (int)ncp->dims.ndefined -1;
-        /* ncp->dims.ndefined has been increased in incr_NC_dimarray() */
+    /* ncp->dims.ndefined has been increased in incr_NC_dimarray() */
+    dimid = (int)ncp->dims.ndefined -1;
 
-    return NC_NOERR;
+    if (size == NC_UNLIMITED) ncp->dims.unlimited_id = dimid;
+
+    if (dimidp != NULL) *dimidp = dimid;
+
+
+    return err;
 }
 
 
@@ -371,20 +523,26 @@ ncmpi_def_dim(int         ncid,    /* IN:  file ID */
 int
 ncmpi_inq_dimid(int         ncid,
                 const char *name,
-                int        *dimid_ptr)
+                int        *dimid)
 {
-    int status;
-    NC *ncp;
-    int dimid;
+    int err;
+    char *nname=NULL; /* normalized name */
+    NC *ncp=NULL;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
-    dimid = NC_finddim(&ncp->dims, name, NULL);
-    if (dimid == -1) DEBUG_RETURN_ERROR(NC_EBADDIM)
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME)
+        DEBUG_RETURN_ERROR(NC_EBADNAME)
 
-    *dimid_ptr = dimid;
-    return NC_NOERR;
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    err = ncmpii_NC_finddim(&ncp->dims, nname, dimid);
+    free(nname);
+
+    return err;
 }
 
 
@@ -396,11 +554,11 @@ ncmpi_inq_dim(int         ncid,
               MPI_Offset *sizep)
 {
     int status;
-    NC *ncp;
-    NC_dim *dimp;
+    NC *ncp=NULL;
+    NC_dim *dimp=NULL;
 
     status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    if (status != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(status)
 
     dimp = ncmpii_elem_NC_dimarray(&ncp->dims, dimid);
     if (dimp == NULL) DEBUG_RETURN_ERROR(NC_EBADDIM)
@@ -440,86 +598,140 @@ ncmpi_inq_dimlen(int         ncid,
 
 
 /*----< ncmpi_rename_dim() >--------------------------------------------------*/
-/* This API is collective if called in data mode */
+/* This API is collective and can be called in either define or data mode..
+ * If the new name is longer than the old name, the netCDF dataset must be in
+ * the define mode.
+ */
 int
 ncmpi_rename_dim(int         ncid,
                  int         dimid,
                  const char *newname)
 {
-    int file_ver, status, existid, err, mpireturn;
-    NC *ncp;
-    NC_dim *dimp;
-
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    int err;
+    char *nnewname=NULL; /* normalized newname */
+    NC *ncp=NULL;
+    NC_dim *dimp=NULL;
+    NC_string *newStr=NULL;
+
+    /* check whether ncid is valid */
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
+
+    /* check file's write permission */
+    if (NC_readonly(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EPERM)
+        goto err_check;
+    }
 
-    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM)
+    if (newname == NULL || *newname == 0 || strlen(newname) > NC_MAX_NAME) {
+        DEBUG_ASSIGN_ERROR(err, NC_EBADNAME)
+        goto err_check;
+    }
 
-    file_ver = 1;
-    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
-        file_ver = 2;
-    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
-        file_ver = 5;
+    /* check whether newname is legal */
+    err = ncmpii_NC_check_name(newname, ncp->format);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
 
-    status = ncmpii_NC_check_name(newname, file_ver);
-    if (status != NC_NOERR) return status;
+    /* create a normalized character string */
+    nnewname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)newname);
+    if (nnewname == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
+    }
 
-    existid = NC_finddim(&ncp->dims, newname, &dimp);
-    if (existid != -1) DEBUG_RETURN_ERROR(NC_ENAMEINUSE)
+    /* check whether newname is already in use */
+    err = ncmpii_NC_finddim(&ncp->dims, nnewname, NULL);
+    if (err != NC_EBADDIM) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENAMEINUSE)
+        goto err_check;
+    }
 
+    /* retrieve dim object */
     dimp = ncmpii_elem_NC_dimarray(&ncp->dims, dimid);
-    if (dimp == NULL) DEBUG_RETURN_ERROR(NC_EBADDIM)
+    if (dimp == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_EBADDIM)
+        goto err_check;
+    }
 
-    if (NC_indef(ncp)) {
-        NC_string *newStr = ncmpii_new_NC_string(strlen(newname), newname);
-        if (newStr == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+    if (! NC_indef(ncp) && /* when file is in data mode */
+        dimp->name->nchars < (MPI_Offset)strlen(nnewname)) {
+        /* must in define mode when newname is longer */
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+        goto err_check;
+    }
 
-        ncmpii_free_NC_string(dimp->name);
-        dimp->name = newStr;
-        return NC_NOERR;
+    newStr = ncmpii_new_NC_string(strlen(nnewname), nnewname);
+    if (newStr == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
     }
-    /* else, not in define mode.
-     * if called in data mode (collective or independent), this function must
-     * be called collectively, i.e. all processes must participate.
-     */
+
+#ifndef SEARCH_NAME_LINEARLY
+    /* update dim name lookup table, by removing the old name and add
+     * the new name */
+    err = ncmpii_update_name_lookup_table(ncp->dims.nameT, dimid,
+          ncp->dims.value[dimid]->name->cp, nnewname);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
+#endif
+
+err_check:
+    if (nnewname != NULL) free(nnewname);
 
     if (ncp->safe_mode) {
-        int nchars = (int)strlen(newname);
-        TRACE_COMM(MPI_Bcast)(&nchars, 1, MPI_INT, 0, ncp->nciop->comm);
+        int root_dimid, status, mpireturn;
+        char root_name[NC_MAX_NAME];
+
+        /* check if newname is consistent among all processes */
+        if (newname == NULL || *newname == 0)
+            root_name[0] = 0;
+        else
+            strncpy(root_name, newname, NC_MAX_NAME);
+        TRACE_COMM(MPI_Bcast)(root_name, NC_MAX_NAME, MPI_CHAR, 0, ncp->nciop->comm);
         if (mpireturn != MPI_SUCCESS)
-            return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && strcmp(root_name, newname))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_DIM_NAME)
 
-        if (nchars != strlen(newname)) {
-            /* newname's length is inconsistent with root's */
-            printf("Warning: dimension name(%s) used in %s() is inconsistent\n",
-                   newname, __func__);
-            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_DIM_NAME)
-        }
-    }
+        /* check if dimid is consistent across all processes */
+        root_dimid = dimid;
+        TRACE_COMM(MPI_Bcast)(&root_dimid, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && root_dimid != dimid)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FNC_ARGS)
 
-    /* ncmpii_set_NC_string() will check for strlen(newname) > nchars error */
-    err = ncmpii_set_NC_string(dimp->name, newname);
-    if (status == NC_NOERR) status = err;
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        if (err == NC_NOERR) err = status;
+    }
 
-    /* PnetCDF expects all processes use the same name, However, when names
-     * are not the same, only root's value is significant. Broadcast the
-     * new name at root to overwrite new names at other processes.
-     * (This API is collective if called in data mode)
-     */
-    TRACE_COMM(MPI_Bcast)(dimp->name->cp, (int)dimp->name->nchars, MPI_CHAR, 0,
-                          ncp->nciop->comm);
-    if (mpireturn != MPI_SUCCESS) {
-        err = ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
-        if (status == NC_NOERR) status = err;
+    if (err != NC_NOERR) {
+        if (newStr != NULL) ncmpii_free_NC_string(newStr);
+        return err;
     }
 
-    /* Let root write the entire header to the file. Note that we cannot just
-     * update the variable name in its space occupied in the file header,
-     * because if the file space occupied by the name shrinks, all the metadata
-     * following it must be moved ahead.
-     */
-    err = ncmpii_write_header(ncp);
-    if (status == NC_NOERR) status = err;
+    /* replace the old name with new name */
+    assert(dimp != NULL);
+    ncmpii_free_NC_string(dimp->name);
+    dimp->name = newStr;
+
+    if (! NC_indef(ncp)) { /* when file is in data mode */
+        /* Let root write the entire header to the file. Note that we cannot
+         * just update the variable name in its space occupied in the file
+         * header, because if the file space occupied by the name shrinks, all
+         * the metadata following it must be moved ahead.
+         */
+        err = ncmpii_write_header(ncp);
+        if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+    }
 
-    return status;
+    return err;
 }
diff --git a/src/lib/error.c b/src/lib/error.c
index 5f0d1bd..9fdd9ee 100644
--- a/src/lib/error.c
+++ b/src/lib/error.c
@@ -2,12 +2,12 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: error.c 2320 2016-02-24 13:18:32Z wkliao $ */
+/* $Id: error.c 2604 2016-11-09 16:10:48Z wkliao $ */
 
 /*LINTLIBRARY*/
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -231,7 +231,7 @@ ncmpi_strerror(int err)
             /* Some APIs require argument count cannot be a NULL pointer
              */
         case NC_EINVAL_CMODE:
-            return "Invalid file create mode, cannot have both NC_64BIT_OFFSET & NC_64BIT_DATA";
+            return "Invalid file create mode";
         case NC_ETYPESIZE:
             return "MPI derived data type size error (bigger than the variable size)";
         case NC_ETYPE_MISMATCH:
@@ -244,6 +244,10 @@ ncmpi_strerror(int err)
             return "Attempting operation only for record variables";
         case NC_ENOTFILL:
             return "Attempting to fill a variable when its fill mode is off";
+        case NC_EINVAL_OMODE:
+            return "Invalid file open mode";
+        case NC_EPENDING:
+            return "Pending nonblocking request is found at file close";
         case NC_EMULTIDEFINE:
             return "File header is inconsistent among processes";
             /* this error means the metadata (dimension names, variable names,
@@ -251,23 +255,25 @@ ncmpi_strerror(int err)
              * in the file header) is inconsistent among all MPI processes.
              */
         case NC_EMULTIDEFINE_OMODE:
-            return "Bad file create/open mode or modes are inconsistent across processes.";
+            return "File open mode is inconsistent among processes.";
         case NC_EMULTIDEFINE_DIM_NUM:
-            return "Number of dimensions is defined inconsistently among processes.";
+            return "Number of dimensions is inconsistent among processes.";
         case NC_EMULTIDEFINE_DIM_SIZE:
-            return "Dimension size is defined inconsistently among processes.";
+            return "Dimension size is inconsistent among processes.";
+        case NC_EMULTIDEFINE_DIM_NAME:
+            return "Dimension name is inconsistent among processes.";
         case NC_EMULTIDEFINE_VAR_NUM:
-            return "Number of variables is defined inconsistently among processes.";
+            return "Number of variables is inconsistent among processes.";
         case NC_EMULTIDEFINE_VAR_NAME:
-            return "Variable names are defined inconsistently among processes.";
+            return "Variable name is inconsistent among processes.";
         case NC_EMULTIDEFINE_VAR_NDIMS:
-            return "Dimensionality of this variable is defined inconsistently among processes.";
+            return "Dimensionality of this variable is inconsistent among processes.";
         case NC_EMULTIDEFINE_VAR_DIMIDS:
-            return "Dimension IDs used to define this variable is inconsistent among processes.";
+            return "Dimension IDs used to define this variable are inconsistent among processes.";
         case NC_EMULTIDEFINE_VAR_TYPE:
-            return "Data type of this variable is defined inconsistently among processes.";
+            return "Data type of this variable is inconsistent among processes.";
         case NC_EMULTIDEFINE_VAR_LEN:
-            return "Number of elements of this variable is defined inconsistently among processes.";
+            return "Number of elements of this variable is inconsistent among processes.";
         case NC_EMULTIDEFINE_VAR_BEGIN:
             return "Starting file offset of this variable is inconsistent among processes.";
         case NC_EMULTIDEFINE_NUMRECS:
@@ -292,6 +298,8 @@ ncmpi_strerror(int err)
             return "Variable's fill mode is inconsistent among processes.";
         case NC_EMULTIDEFINE_VAR_FILL_VALUE:
             return "Variable's fill value is inconsistent among processes.";
+        case NC_EMULTIDEFINE_CMODE:
+            return "File create mode is inconsistent among processes.";
 
         default:
             /* check netCDF-3 and netCDF-4 errors */
@@ -304,7 +312,7 @@ ncmpi_strerror(int err)
 int ncmpii_handle_error(int   mpi_errorcode, /* returned value from MPI call */
                         char *err_msg)       /* extra error message */
 {
-    int rank, errorclass, errorStringLen;
+    int errorclass, errorStringLen;
     char errorString[MPI_MAX_ERROR_STRING];
 
     /* check for specific error codes understood by PnetCDF */
@@ -359,11 +367,16 @@ int ncmpii_handle_error(int   mpi_errorcode, /* returned value from MPI call */
 
     /* other errors that currently have no corresponding PnetCDF error codes */
 
-    /* we report the world rank */
-    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
     MPI_Error_string(mpi_errorcode, errorString, &errorStringLen);
     if (err_msg == NULL) err_msg = "";
+#ifdef PNETCDF_DEBUG
+    /* report the world rank */
+    int rank;
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
     printf("rank %d: MPI error (%s) : %s\n", rank, err_msg, errorString);
+#else
+    printf("MPI error (%s) : %s\n", err_msg, errorString);
+#endif
 
     return NC_EFILE; /* other unknown file I/O error */
 }
@@ -612,9 +625,22 @@ nc_strerror(int ncerr1)
 }
 /** \} */
 
-char* ncmpii_err_code_name(int err)
+/*----< ncmpi_strerrno() >---------------------------------------------------*/
+/* print the NC error code name */
+const char *
+ncmpi_strerrno(int err)
 {
     static char unknown_str[32];
+
+    if (err > 0) { /* system error */
+        const char *cp = (const char *) strerror(err);
+        if (cp == NULL)
+            sprintf(unknown_str,"Unknown error code %d",err);
+        else
+            sprintf(unknown_str,"Error code %d (%s)",err,cp);
+        return unknown_str;
+    }
+
     switch (err) {
         case (NC_NOERR):			return "NC_NOERR";
         case (NC_EBADID):			return "NC_EBADID";
@@ -726,6 +752,8 @@ char* ncmpii_err_code_name(int err)
         case (NC_ENULLSTART):			return "NC_ENULLSTART";
         case (NC_ENULLCOUNT):			return "NC_ENULLCOUNT";
         case (NC_EINVAL_CMODE):			return "NC_EINVAL_CMODE";
+        case (NC_EINVAL_OMODE):			return "NC_EINVAL_OMODE";
+        case (NC_EPENDING):			return "NC_EPENDING";
         case (NC_ETYPESIZE):			return "NC_ETYPESIZE";
         case (NC_ETYPE_MISMATCH):		return "NC_ETYPE_MISMATCH";
         case (NC_ETYPESIZE_MISMATCH):		return "NC_ETYPESIZE_MISMATCH";
@@ -755,6 +783,7 @@ char* ncmpii_err_code_name(int err)
         case (NC_EMULTIDEFINE_FILL_MODE):	return "NC_EMULTIDEFINE_FILL_MODE";
         case (NC_EMULTIDEFINE_VAR_FILL_MODE):	return "NC_EMULTIDEFINE_VAR_FILL_MODE";
         case (NC_EMULTIDEFINE_VAR_FILL_VALUE):	return "NC_EMULTIDEFINE_VAR_FILL_VALUE";
+        case (NC_EMULTIDEFINE_CMODE):		return "NC_EMULTIDEFINE_CMODE";
         default:
               sprintf(unknown_str,"Unknown code %d",err);
     }
diff --git a/src/lib/filetype.c b/src/lib/filetype.c
index 5a80642..231dcb5 100644
--- a/src/lib/filetype.c
+++ b/src/lib/filetype.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: filetype.c 2335 2016-03-03 14:55:12Z wkliao $ */
+/* $Id: filetype.c 2603 2016-11-08 19:04:56Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -66,10 +66,10 @@ NC_start_count_stride_ck(const NC         *ncp,
     if (varp->ndims == 0) return NC_NOERR; /* 'scalar' variable */
 
     /* negative start[] is illegal */
-    if (start[0] < 0) DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+    if (start == NULL || start[0] < 0) DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
 
     if (IS_RECVAR(varp)) {
-        if (!fIsSet(ncp->flags, NC_64BIT_DATA) && /* not CDF-5 */
+        if (ncp->format < 5 && /* not CDF-5 */
             start[0] > X_UINT_MAX) /* sanity check */
             DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
 
@@ -78,10 +78,16 @@ NC_start_count_stride_ck(const NC         *ncp,
 
         /* for record variable, [0] is the NC_UNLIMITED dimension */
         if (rw_flag == READ_REQ) { /* read cannot go beyond current numrecs */
-            if (start[0] >= ncp->numrecs)
-                DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
-
+#ifdef RELAX_COORD_BOUND
+            if (start[0] > ncp->numrecs) DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+#else
+            if (start[0] >= ncp->numrecs) DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+#endif
             if (count != NULL) {
+#ifdef RELAX_COORD_BOUND
+                if (start[0] == ncp->numrecs && count[0] > 0)
+                    DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+#endif
                 if (stride == NULL) { /* for vara APIs */
                     if (start[0] + count[0] > ncp->numrecs)
                         DEBUG_RETURN_ERROR(NC_EEDGE)
@@ -121,8 +127,16 @@ NC_start_count_stride_ck(const NC         *ncp,
     }
 
     for (; i<varp->ndims; i++) {
+#ifdef RELAX_COORD_BOUND
+        if (start[i] < 0 || start[i] > varp->shape[i])
+            DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+
+        if (count != NULL && start[i] == varp->shape[i] && count[i] > 0)
+            DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+#else
         if (start[i] < 0 || start[i] >= varp->shape[i])
             DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+#endif
 
         if (varp->shape[i] < 0) DEBUG_RETURN_ERROR(NC_EEDGE)
 
@@ -148,7 +162,10 @@ NC_start_count_stride_ck(const NC         *ncp,
 }
 
 /*----< ncmpii_get_offset() >------------------------------------------------*/
-/* returns the file offset of the last byte accessed of this request */
+/* returns the file offset of the last byte accessed of this request
+ * If counts is NULL, this is equivalent to the starting offset of this
+ * request
+ */
 int
 ncmpii_get_offset(NC               *ncp,
                   NC_var           *varp,
@@ -919,7 +936,7 @@ ncmpii_vars_create_filetype(NC               *ncp,
 int
 ncmpii_file_set_view(NC           *ncp,
                      MPI_File      fh,
-                     MPI_Offset   *offset,
+                     MPI_Offset   *offset,  /* IN/OUT */
                      MPI_Datatype  filetype)
 {
     int rank, err, mpireturn, status=NC_NOERR;
diff --git a/src/lib/fill.c b/src/lib/fill.c
index 22b491b..3c4b59e 100644
--- a/src/lib/fill.c
+++ b/src/lib/fill.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: fill.c 2320 2016-02-24 13:18:32Z wkliao $ */
+/* $Id: fill.c 2609 2016-11-11 01:11:45Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #ifdef HAVE_STDLIB_H
@@ -13,6 +13,7 @@
 #endif
 #include <stdio.h>
 #include <string.h>
+#include <assert.h>
 
 #include <mpi.h>
 
@@ -57,25 +58,25 @@ static unsigned char FILL_UINT[4]   = {0xFF, 0xFF, 0xFF, 0xFF};
 static unsigned char FILL_INT64[8]  = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
 static unsigned char FILL_UINT64[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE};
 
-/*----< inq_default_fill_value() >-------------------------------------------*/
+/*----< ncmpii_inq_default_fill_value() >------------------------------------*/
 /* copy the default fill value to the memory space pointed by fill_value */
-static int
-inq_default_fill_value(int type, void *fill_value)
+int
+ncmpii_inq_default_fill_value(int xtype, void *fillp)
 {
-    if (fill_value == NULL) return NC_NOERR;
-
-    switch(type) {
-        case NC_CHAR   :               *(char*)fill_value = NC_FILL_CHAR;   break;
-        case NC_BYTE   :        *(signed char*)fill_value = NC_FILL_BYTE;   break;
-        case NC_SHORT  :              *(short*)fill_value = NC_FILL_SHORT;  break;
-        case NC_INT    :                *(int*)fill_value = NC_FILL_INT;    break;
-        case NC_FLOAT  :              *(float*)fill_value = NC_FILL_FLOAT;  break;
-        case NC_DOUBLE :             *(double*)fill_value = NC_FILL_DOUBLE; break;
-        case NC_UBYTE  :      *(unsigned char*)fill_value = NC_FILL_UBYTE;  break;
-        case NC_USHORT :     *(unsigned short*)fill_value = NC_FILL_USHORT; break;
-        case NC_UINT   :       *(unsigned int*)fill_value = NC_FILL_UINT;   break;
-        case NC_INT64  :          *(long long*)fill_value = NC_FILL_INT64;  break;
-        case NC_UINT64 : *(unsigned long long*)fill_value = NC_FILL_UINT64; break;
+    if (fillp == NULL) return NC_NOERR;
+
+    switch(xtype) {
+        case NC_CHAR   :               *(char*)fillp = NC_FILL_CHAR;   break;
+        case NC_BYTE   :        *(signed char*)fillp = NC_FILL_BYTE;   break;
+        case NC_SHORT  :              *(short*)fillp = NC_FILL_SHORT;  break;
+        case NC_INT    :                *(int*)fillp = NC_FILL_INT;    break;
+        case NC_FLOAT  :              *(float*)fillp = NC_FILL_FLOAT;  break;
+        case NC_DOUBLE :             *(double*)fillp = NC_FILL_DOUBLE; break;
+        case NC_UBYTE  :      *(unsigned char*)fillp = NC_FILL_UBYTE;  break;
+        case NC_USHORT :     *(unsigned short*)fillp = NC_FILL_USHORT; break;
+        case NC_UINT   :       *(unsigned int*)fillp = NC_FILL_UINT;   break;
+        case NC_INT64  :          *(long long*)fillp = NC_FILL_INT64;  break;
+        case NC_UINT64 : *(unsigned long long*)fillp = NC_FILL_UINT64; break;
         default : DEBUG_RETURN_ERROR(NC_EBADTYPE)
     }
     return NC_NOERR;
@@ -225,31 +226,77 @@ ncmpi_fill_var_rec(int        ncid,
 {
     int     indx, err;
     NC     *ncp;
-    NC_var *varp;
+    NC_var *varp=NULL;
 
     /* check if ncid is valid */
     err = ncmpii_NC_check_id(ncid, &ncp);
-    if (err != NC_NOERR) return err;
-
-    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM) /* read-only */
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
-    /* This must be called in data mode */
-    if (NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_EINDEFINE)                                
+    /* check file's write permission */
+    if (NC_readonly(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EPERM)
+        goto err_check;
+    }
 
-    /* must be called in collective data mode */
-    if (NC_indep(ncp)) DEBUG_RETURN_ERROR(NC_EINDEP)
+    /* must be called in data mode */
+    if (NC_indef(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EINDEFINE)
+        goto err_check;
+    }
 
+    /* check whether variable ID is valid */
     err = ncmpii_NC_lookupvar(ncp, varid, &varp);
-    if (err != NC_NOERR) return err;
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
 
     /* error if this is not a record variable */
-    if (!IS_RECVAR(varp)) DEBUG_RETURN_ERROR(NC_ENOTRECVAR)
+    if (!IS_RECVAR(varp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTRECVAR)
+        goto err_check;
+    }
 
     /* check if _FillValue attribute is defined */
     indx = ncmpii_NC_findattr(&varp->attrs, _FillValue);
 
     /* error if the fill mode of this variable is not on */
-    if (varp->no_fill && indx == -1) DEBUG_RETURN_ERROR(NC_ENOTFILL)
+    if (varp->no_fill && indx == -1) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTFILL)
+        goto err_check;
+    }
+
+err_check:
+    if (ncp->safe_mode) { /* consistency check */
+        int root_varid, status, mpireturn;
+        MPI_Offset root_recno;
+
+        /* check if varid is consistent across all processes */
+        root_varid = varid;
+        TRACE_COMM(MPI_Bcast)(&root_varid, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && root_varid != varid)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FNC_ARGS)
+
+        /* check if recno is consistent across all processes */
+        root_recno = recno;
+        TRACE_COMM(MPI_Bcast)(&root_recno, 1, MPI_OFFSET, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && root_recno != recno)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FNC_ARGS)
+
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+
+        if (err == NC_NOERR) err = status;
+    }
+    if (err != NC_NOERR) return err;
+
+    assert(varp != NULL);
 
     return ncmpii_fill_var_rec(ncp, varp, recno);
 }
@@ -257,36 +304,51 @@ ncmpi_fill_var_rec(int        ncid,
 /*----< ncmpi_set_fill() >---------------------------------------------------*/
 /* this API is collective, must be called in define mode, contrary to netCDF
  * where nc_set_fill() can also be called in data mode. The reason of PnetCDF
- * enforcing this requirement is because PnetCDF only fills fix-sized variables
- * at ncmpi_enddef() and record variables in ncmpi_fill_var_rec().
+ * enforcing this requirement is because PnetCDF only fills fixed-size
+ * variables at ncmpi_enddef() and record variables in ncmpi_fill_var_rec().
  */
 int
 ncmpi_set_fill(int  ncid,
                int  fill_mode,
                int *old_fill_mode)
 {
-    int i, status=NC_NOERR, mpireturn, oldmode;
+    int i, err, mpireturn, oldmode;
     NC *ncp;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    /* check whether ncid is valid */
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
-    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM) /* read-only */
+    /* check whether file's write permission */
+    if (NC_readonly(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EPERM)
+        goto err_check;
+    }
 
     /* check if called in define mode */
-    if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+    if (!NC_indef(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+        goto err_check;
+    }
 
+err_check:
     if (ncp->safe_mode) {
-        int root_fill_mode=fill_mode;
+        int status, root_fill_mode=fill_mode;
+
         TRACE_COMM(MPI_Bcast)(&root_fill_mode, 1, MPI_INT, 0, ncp->nciop->comm);
         if (mpireturn != MPI_SUCCESS)
             return  ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
-        if (fill_mode != root_fill_mode) {
+        if (err == NC_NOERR && fill_mode != root_fill_mode)
             /* dataset's fill mode is inconsistent with root's */
-            printf("Warning: fill mode set in %s() is inconsistent\n", __func__);
-            DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_FILL_MODE)
-        }
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FILL_MODE)
+
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        if (err == NC_NOERR) err = status;
     }
+    if (err != NC_NOERR) return err;
 
     oldmode = fIsSet(ncp->flags, NC_NOFILL) ? NC_NOFILL : NC_FILL;
 
@@ -301,13 +363,13 @@ ncmpi_set_fill(int  ncid,
 
     /* loop thru all variables defined so far to set/overwrite its fill mode */
     for (i=0; i<ncp->vars.ndefined; i++)
-        ncp->vars.value[i]->no_fill = (fill_mode == NC_NOFILL) ? 1 : 0;
+        ncp->vars.value[i]->no_fill = (char)((fill_mode == NC_NOFILL) ? 1 : 0);
 
     /* once the file's fill mode is set, any new variables defined after this
      * call will check NC_dofill(ncp) and set their no_fill accordingly. See
      * ncmpi_def_var() */
 
-    return status;
+    return NC_NOERR;
 }
 
 /*----< ncmpi_def_var_fill() >------------------------------------------------*/
@@ -318,63 +380,73 @@ ncmpi_def_var_fill(int   ncid,
                    int   no_fill,    /* 1: no fill, 0: fill */
                    void *fill_value) /* when NULL, use default fill value */
 {
-    int err, status=NC_NOERR, mpireturn, free_fill_value=0;
+    int err;
     NC *ncp;
-    NC_var *varp;
+    NC_var *varp=NULL;
 
+    /* check whether ncid is valid */
     err = ncmpii_NC_check_id(ncid, &ncp);
-    if (err != NC_NOERR) return err;
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
-    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM) /* read-only */
+    /* check whether file's write permission */
+    if (NC_readonly(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EPERM)
+        goto err_check;
+    }
 
-    /* must be called in define mode */
-    if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+    /* check if called in define mode */
+    if (!NC_indef(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+        goto err_check;
+    }
 
-    /* find the pointer to this variable's object */
+    /* check whether variable ID is valid */
     err = ncmpii_NC_lookupvar(ncp, varid, &varp);
-    if (err != NC_NOERR) return err;
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
 
+err_check:
     if (ncp->safe_mode) {
-        int root_no_fill=no_fill;
-        TRACE_COMM(MPI_Bcast)(&root_no_fill, 1, MPI_INT, 0, ncp->nciop->comm);
+        int root_ids[3], my_fill_null, status, mpireturn;
+
+        /* check if varid, no_fill, fill_value, are consistent across all processes */
+        my_fill_null = (fill_value == NULL) ? 1 : 0;;
+        root_ids[0] = varid;
+        root_ids[1] = no_fill;
+        root_ids[2] = my_fill_null;
+        TRACE_COMM(MPI_Bcast)(&root_ids, 3, MPI_INT, 0, ncp->nciop->comm);
         if (mpireturn != MPI_SUCCESS)
-            return  ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
-
-        if (no_fill != root_no_fill) {
-            /* variable's fill mode is inconsistent with root's */
-            printf("Warning: variable (%s) fill mode (%d) set in %s() is inconsistent\n",
-                   varp->name->cp, no_fill, __func__);
-            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_VAR_FILL_MODE)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && (root_ids[0] != varid ||
+            root_ids[1] != no_fill || root_ids[2] != my_fill_null))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FNC_ARGS)
+
+        /* check fill_value, if not NULL, is consistent among processes */
+        if (varp!= NULL && root_ids[2] == 0) {
+            double root_fill_value; /* max nc_type space: 8 bytes */
+            if (fill_value != NULL)
+                memcpy(&root_fill_value, fill_value, (size_t)varp->xsz);
+            TRACE_COMM(MPI_Bcast)(&root_fill_value, varp->xsz, MPI_BYTE, 0, ncp->nciop->comm);
+            if (mpireturn != MPI_SUCCESS)
+                return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+            if (err == NC_NOERR && fill_value != NULL &&
+                memcmp(fill_value, &root_fill_value, (size_t)varp->xsz))
+                /* variable's fill value is inconsistent with root's */
+                DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_FILL_VALUE)
         }
 
-        /* check if fill_value is consistent among processes */
-        void *root_fill_value = NCI_Malloc((size_t)varp->xsz);
-        if (fill_value == NULL) {
-            /* user intends to use default fill value */
-            fill_value = NCI_Malloc((size_t)varp->xsz);
-            err = inq_default_fill_value(varp->type, fill_value);
-            if (err != NC_NOERR) {
-                NCI_Free(fill_value);
-                NCI_Free(root_fill_value);
-                return err;
-            }
-            free_fill_value=1;
-        }
-        memcpy(root_fill_value, fill_value, (size_t)varp->xsz);
-            
-        TRACE_COMM(MPI_Bcast)(root_fill_value, varp->xsz, MPI_BYTE, 0, ncp->nciop->comm);
-        if (memcmp(fill_value, root_fill_value, (size_t)varp->xsz)) {
-            /* variable's fill value is inconsistent with root's */
-            printf("Warning: variable (%s) fill value set in %s() is inconsistent\n",
-                   varp->name->cp, __func__);
-            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_VAR_FILL_VALUE)
-        }
-        if (free_fill_value) {
-            NCI_Free(fill_value);
-            fill_value = NULL;
-        }
-        NCI_Free(root_fill_value);
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+
+        if (err == NC_NOERR) err = status;
     }
+    if (err != NC_NOERR) return err;
+
+    assert(varp != NULL);
 
     if (no_fill)
         varp->no_fill = 1;
@@ -394,7 +466,7 @@ ncmpi_def_var_fill(int   ncid,
         if (err != NC_NOERR) return err;
     }
 
-    return status;
+    return NC_NOERR;
 }
 
 /*----< ncmpi_inq_var_fill() >-----------------------------------------------*/
@@ -416,14 +488,14 @@ ncmpi_inq_var_fill(int   ncid,
     err = ncmpii_NC_lookupvar(ncp, varid, &varp);
     if (err != NC_NOERR) return err;
 
-    *no_fill = varp->no_fill;
+    if (no_fill != NULL) *no_fill = varp->no_fill;
 
     if (fill_value != NULL) {
         err = ncmpi_get_att(ncid, varid, _FillValue, fill_value);
         if (err != NC_NOERR && err != NC_ENOTATT)
             return err;
         if (err == NC_ENOTATT) {
-            err = inq_default_fill_value(varp->type, fill_value);
+            err = ncmpii_inq_default_fill_value(varp->type, fill_value);
             if (err != NC_NOERR) return err;
         }
     }
@@ -431,6 +503,39 @@ ncmpi_inq_var_fill(int   ncid,
     return NC_NOERR;
 }
 
+/*----< ncmpii_inq_var_fill() >----------------------------------------------*/
+int
+ncmpii_inq_var_fill(NC_var *varp,
+                    void   *fill_value) /* OUT: user-defined or
+                                                default fill value */
+{
+    int i;
+    size_t nchars;
+    NC_attrarray *attrs;
+
+    assert(varp != NULL); /* NC_GLOBAL varid is illegal in this context */
+
+    nchars = strlen("_FillValue");
+
+    /* Check if _FillValue is defined for this variable */
+    attrs = &varp->attrs;
+    for (i=0; i<attrs->ndefined; i++) {
+        if (attrs->value[i]->name->nchars == nchars &&
+            strncmp(attrs->value[i]->name->cp, "_FillValue", nchars) == 0) {
+            memcpy(fill_value, attrs->value[i]->xvalue, (size_t)varp->xsz);
+            return NC_NOERR;
+        }
+    }
+
+    /* NetCDF 4.4.1 and prior does not use global attribute _FillValue if
+     * it is not defined for the variable. Default fill values are used.
+     * See fill_NC_var() in putget.m4.
+     */
+
+    /* return default _FillValue */
+    return ncmpii_inq_default_fill_value(varp->type, fill_value);
+}
+
 #ifdef FILL_ONE_VAR_AT_A_TIME
 /*----< fillerup() >---------------------------------------------------------*/
 /* fill the newly created fixed-size variables */
@@ -526,13 +631,13 @@ fill_added_recs(NC *ncp, NC *old_ncp)
 static int
 fillerup_aggregate(NC *ncp, NC *old_ncp)
 {
-    int i, j, k, rank, nprocs, start_vid, nsegs, recno;
+    int i, j, k, rank, nprocs, start_vid, recno;
     int nVarsFill, *blocklengths;
     int mpireturn, err, status=NC_NOERR;
     char *buf_ptr, *noFill;
     void *buf;
-    size_t buf_len;
-    MPI_Offset var_len, nrecs, start, *count;
+    size_t nsegs;
+    MPI_Offset buf_len, var_len, nrecs, start, *count;
     MPI_Aint *offset;
     MPI_Datatype filetype;
     MPI_File fh;
@@ -550,28 +655,36 @@ fillerup_aggregate(NC *ncp, NC *old_ncp)
         nrecs = NC_get_numrecs(old_ncp);
     }
 
+    noFill = (char*) NCI_Malloc((size_t)(ncp->vars.ndefined - start_vid));
+    nVarsFill = 0;
+
+#ifdef _CHECK_FILL_MODE_CONSISTENCY
     /* Because fill mode is not part of file header, we must broadcast root's
      * variables' fill modes and overwrite local's if an inconsistency is found
      * Note ncp->vars.ndefined is already made consistent by this point.
      */
-    noFill = (char*) NCI_Malloc(ncp->vars.ndefined - start_vid);
     for (i=start_vid; i<ncp->vars.ndefined; i++)
         noFill[i-start_vid] = ncp->vars.value[i]->no_fill;
-
     TRACE_COMM(MPI_Bcast)(noFill, (ncp->vars.ndefined - start_vid), MPI_BYTE, 0,
                           ncp->nciop->comm);
-    nVarsFill = 0;
-    for (i=start_vid; i<ncp->vars.ndefined; i++) { /* overwrite local's mode */
+    for (i=start_vid; i<ncp->vars.ndefined; i++) {
+        /* overwrite local's mode */
         ncp->vars.value[i]->no_fill = noFill[i-start_vid];
         if (!noFill[i-start_vid]) nVarsFill++;
     }
+#else
+    for (i=start_vid; i<ncp->vars.ndefined; i++) {
+        noFill[i-start_vid] = ncp->vars.value[i]->no_fill;
+        if (!noFill[i-start_vid]) nVarsFill++;
+    }
+#endif
     if (nVarsFill == 0) { /* no variables in fill mode */
         NCI_Free(noFill);
         return NC_NOERR;
     }
 
     /* find the number of write segments (upper bound) */
-    nsegs = ncp->vars.ndefined + ncp->vars.num_rec_vars * nrecs;
+    nsegs = (size_t)(ncp->vars.ndefined + ncp->vars.num_rec_vars * nrecs);
     count  = (MPI_Offset*) NCI_Malloc(nsegs * sizeof(MPI_Offset));
     offset = (MPI_Aint*)   NCI_Malloc(nsegs * sizeof(MPI_Aint));
 
@@ -611,7 +724,7 @@ fillerup_aggregate(NC *ncp, NC *old_ncp)
         /* add up the buffer size */
         buf_len += count[j] * varp->xsz;
 
-        j++;
+        j++; /* increase j even when count[j] is zero */
     }
 
     /* loop thru all record variables to find the aggregated write amount */
@@ -648,14 +761,21 @@ fillerup_aggregate(NC *ncp, NC *old_ncp)
             /* add up the buffer size */
             buf_len += count[j] * varp->xsz;
 
-            j++;
+            j++; /* increase j even when count[j] is zero */
         }
     }
     /* j is now the number of valid write segments */
 
+    if (status == NC_NOERR && j == 0) {
+        NCI_Free(noFill);
+        NCI_Free(count);
+        NCI_Free(offset);
+        return NC_NOERR;
+    }
+
     /* allocate one contiguous buffer space for all writes */
-    blocklengths = (int*) NCI_Malloc(j * sizeof(int));
-    buf = NCI_Malloc(buf_len);
+    blocklengths = (int*) NCI_Malloc((size_t)j * sizeof(int));
+    buf = NCI_Malloc((size_t)buf_len);
     buf_ptr = (char*)buf;
 
     /* fill write buffers for fixed-size variables first */
@@ -722,20 +842,26 @@ fillerup_aggregate(NC *ncp, NC *old_ncp)
     /* k is the number of valid write requests */
     NCI_Free(noFill);
 
-    /* create the fileview: a list of contiguous segment for each variable */
+    if (k == 0) {
+        filetype = MPI_BYTE;
+    }
+    else {
+        /* create fileview: a list of contiguous segment for each variable */
 #ifdef HAVE_MPI_TYPE_CREATE_HINDEXED
-    mpireturn = MPI_Type_create_hindexed(k, blocklengths, offset, MPI_BYTE,
-                                         &filetype);
+        mpireturn = MPI_Type_create_hindexed(k, blocklengths, offset, MPI_BYTE,
+                                             &filetype);
 #else
-    mpireturn = MPI_Type_hindexed(k, blocklengths, offset, MPI_BYTE, &filetype);
+        mpireturn = MPI_Type_hindexed(k, blocklengths, offset, MPI_BYTE,
+                                      &filetype);
 #endif
-    if (mpireturn != MPI_SUCCESS) {
-        int err = ncmpii_handle_error(mpireturn, "MPI_Type_hindexed");
-        /* return the first encountered error if there is any */
-        if (status == NC_NOERR) status = err;
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_Type_hindexed");
+            /* return the first encountered error if there is any */
+            if (status == NC_NOERR) status = err;
+        }
+        else
+            MPI_Type_commit(&filetype);
     }
-    else
-        MPI_Type_commit(&filetype);
 
     NCI_Free(blocklengths);
     NCI_Free(count);
@@ -745,10 +871,14 @@ fillerup_aggregate(NC *ncp, NC *old_ncp)
 
     TRACE_IO(MPI_File_set_view)(fh, 0, MPI_BYTE, filetype, "native",
                                 MPI_INFO_NULL);
-    MPI_Type_free(&filetype);
+    if (k > 0) MPI_Type_free(&filetype);
+
+    if (buf_len != (int)buf_len)
+        if (status == NC_NOERR)
+            status = NC_EINTOVERFLOW;
 
     /* write to variable collectively */
-    TRACE_IO(MPI_File_write_at_all)(fh, 0, buf, buf_len, MPI_BYTE, &mpistatus);
+    TRACE_IO(MPI_File_write_at_all)(fh, 0, buf, (int)buf_len, MPI_BYTE, &mpistatus);
 
     NCI_Free(buf);
 
diff --git a/src/lib/getput.m4 b/src/lib/getput.m4
index 1506143..0f35d1a 100644
--- a/src/lib/getput.m4
+++ b/src/lib/getput.m4
@@ -7,10 +7,10 @@ dnl
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: getput.m4 2322 2016-02-26 22:47:06Z wkliao $ */
+/* $Id: getput.m4 2588 2016-10-30 04:14:15Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -36,7 +36,7 @@ dnl
 /* check NC_ECHAR and obtain the following metadata about buftype:
  * ptype: element data type (MPI primitive type) in buftype
  * bufcount: If it is -1, then this is called from a high-level API and in
- * this case buftype will be an MPI primitive data type. If not, then this
+ * this case buftype will be an MPI primitive data type. If not -1, then this
  * is called from a flexible API. In that case, we recalculate bufcount to
  * match with count[].
  * bnelems: number of ptypes in user buffer
@@ -54,7 +54,7 @@ ncmpii_calc_datatype_elems(NC               *ncp,
                            int               rw_flag,
                            MPI_Datatype      buftype,
                            MPI_Datatype     *ptype,             /* out */
-                           MPI_Offset       *bufcount,          /* out */
+                           MPI_Offset       *bufcount,          /* in/out */
                            MPI_Offset       *bnelems,           /* out */
                            MPI_Offset       *nbytes,            /* out */
                            int              *el_size,           /* out */
@@ -149,7 +149,7 @@ ncmpii_create_imaptype(NC_var           *varp,
                        MPI_Datatype      ptype,   /* element type in buftype */
                        MPI_Datatype     *imaptype)/* out */
 {
-    int dim;
+    int dim, mpireturn;
     MPI_Offset imap_contig_blocklen;
 
     /* check if this is a vars call or a true varm call */
@@ -188,23 +188,47 @@ ncmpii_create_imaptype(NC_var           *varp,
     if (count[dim] != (int)count[dim] || imap[dim] != (int)imap[dim])
         DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
 
-    MPI_Type_vector((int)count[dim], (int)imap_contig_blocklen, (int)imap[dim],
-                    ptype, imaptype);
-    MPI_Type_commit(imaptype);
+    mpireturn = MPI_Type_vector((int)count[dim], (int)imap_contig_blocklen,
+                                (int)imap[dim], ptype, imaptype);
+    if (mpireturn != MPI_SUCCESS) {
+        ncmpii_handle_error(mpireturn,"MPI_Type_vector");
+        DEBUG_RETURN_ERROR(NC_EMPI)
+    }
+    mpireturn = MPI_Type_commit(imaptype);
+    if (mpireturn != MPI_SUCCESS) {
+        ncmpii_handle_error(mpireturn,"MPI_Type_commit");
+        DEBUG_RETURN_ERROR(NC_EMPI)
+    }
 
     for (dim--; dim>=0; dim--) {
         MPI_Datatype tmptype;
         if (count[dim] != (int)count[dim])
             DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
 #ifdef HAVE_MPI_TYPE_CREATE_HVECTOR
-        MPI_Type_create_hvector((int)count[dim], 1, imap[dim]*el_size,
-                                *imaptype, &tmptype);
+        mpireturn = MPI_Type_create_hvector((int)count[dim], 1,
+                    imap[dim]*el_size, *imaptype, &tmptype);
+        if (mpireturn != MPI_SUCCESS) {
+            ncmpii_handle_error(mpireturn,"MPI_Type_create_hvector");
+            DEBUG_RETURN_ERROR(NC_EMPI)
+        }
 #else
-        MPI_Type_hvector((int)count[dim], 1, imap[dim]*el_size, *imaptype,
-                         &tmptype);
+        mpireturn = MPI_Type_hvector((int)count[dim], 1, imap[dim]*el_size,
+                    *imaptype, &tmptype);
+        if (mpireturn != MPI_SUCCESS) {
+            ncmpii_handle_error(mpireturn,"MPI_Type_hvector");
+            DEBUG_RETURN_ERROR(NC_EMPI)
+        }
 #endif
-        MPI_Type_free(imaptype);
-        MPI_Type_commit(&tmptype);
+        mpireturn = MPI_Type_free(imaptype);
+        if (mpireturn != MPI_SUCCESS) {
+            ncmpii_handle_error(mpireturn,"MPI_Type_free");
+            DEBUG_RETURN_ERROR(NC_EMPI)
+        }
+        mpireturn = MPI_Type_commit(&tmptype);
+        if (mpireturn != MPI_SUCCESS) {
+            ncmpii_handle_error(mpireturn,"MPI_Type_commit");
+            DEBUG_RETURN_ERROR(NC_EMPI)
+        }
         *imaptype = tmptype;
     }
     return NC_NOERR;
@@ -357,7 +381,7 @@ err_check:
     }
 
     /* check if type conversion and Endianness byte swap is needed */
-    need_convert = ncmpii_need_convert(varp->type, ptype);
+    need_convert = ncmpii_need_convert(ncp->format, varp->type, ptype);
     need_swap    = ncmpii_need_swap(varp->type, ptype);
 
     /* Check if this is a vars call or a true varm call.
@@ -405,10 +429,18 @@ err_check:
          */
         xbuf = cbuf;
         if (need_convert) { /* user buf type != nc var type defined in file */
+            void *fillp; /* fill value in internal representation */
+
             xbuf = NCI_Malloc((size_t)nbytes);
 
+            /* find the fill value */
+            fillp = NCI_Malloc((size_t)varp->xsz);
+            ncmpii_inq_var_fill(varp, fillp);
             /* datatype conversion + byte-swap from cbuf to xbuf */
-            DATATYPE_PUT_CONVERT(varp->type, xbuf, cbuf, bnelems, ptype, status)
+            DATATYPE_PUT_CONVERT(ncp->format, varp->type, xbuf, cbuf, bnelems,
+                                 ptype, fillp, status)
+            NCI_Free(fillp);
+
             /* NC_ERANGE can be caused by a subset of buf that is out of range
              * of the external data type, it is not considered a fatal error.
              * The request must continue to finish.
@@ -427,13 +459,14 @@ err_check:
         }
         else if (need_swap) { /* no need to convert, just byte swap */
 #ifdef DISABLE_IN_PLACE_SWAP
-            if (cbuf == buf) {
+            if (cbuf == buf)
 #else
-            if (cbuf == buf && nbytes <= NC_BYTE_SWAP_BUFFER_SIZE) {
+            if (cbuf == buf && nbytes <= NC_BYTE_SWAP_BUFFER_SIZE)
 #endif
+            {
                 /* allocate cbuf and copy buf to xbuf, before byte-swap */
                 xbuf = NCI_Malloc((size_t)nbytes);
-                memcpy(xbuf, buf, nbytes);
+                memcpy(xbuf, buf, (size_t)nbytes);
             }
 
             /* perform array in-place byte-swap on xbuf */
@@ -483,6 +516,9 @@ mpi_io:
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
+            else {
+                ncp->nciop->put_size += nbytes;
+            }
         }
         else { /* io_method == INDEP_IO */
             TRACE_IO(MPI_File_write_at)(fh, offset, xbuf, (int)nbytes,
@@ -495,10 +531,10 @@ mpi_io:
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
+            else {
+                ncp->nciop->put_size += nbytes;
+            }
         }
-        int put_size;
-        MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
-        ncp->nciop->put_size += put_size;
     }
     else {  /* rw_flag == READ_REQ */
         if (io_method == COLL_IO) {
@@ -512,6 +548,9 @@ mpi_io:
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
+            else {
+                ncp->nciop->get_size += nbytes;
+            }
         }
         else { /* io_method == INDEP_IO */
             TRACE_IO(MPI_File_read_at)(fh, offset, xbuf, (int)nbytes,
@@ -524,10 +563,10 @@ mpi_io:
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
+            else {
+                ncp->nciop->get_size += nbytes;
+            }
         }
-        int get_size;
-        MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
-        ncp->nciop->get_size += get_size;
     }
 
     /* No longer need to reset the file view, as the root's fileview includes
@@ -553,7 +592,9 @@ mpi_io:
                 cbuf = NCI_Malloc((size_t)insize);
 
             /* type conversion + byte-swap from xbuf to cbuf */
-            DATATYPE_GET_CONVERT(varp->type, xbuf, cbuf, bnelems, ptype, err)
+            DATATYPE_GET_CONVERT(ncp->format, varp->type, xbuf, cbuf, bnelems,
+                                 ptype, err)
+
             /* retain the first error status */
             if (status == NC_NOERR) status = err;
             NCI_Free(xbuf);
@@ -651,596 +692,58 @@ mpi_io:
     return ((warning != NC_NOERR) ? warning : status);
 }
 
-
-define(`CollIndep', `ifelse(`$1', `_all', `COLL_IO', `INDEP_IO')')dnl
-define(`ReadWrite', `ifelse(`$1', `get',  `READ_REQ', `WRITE_REQ')')dnl
-define(`BufConst',  `ifelse(`$1', `put',  `const')')dnl
-
-dnl
-dnl VAR_FLEXIBLE
-dnl
-define(`VAR_FLEXIBLE',dnl
-`dnl
-/*----< ncmpi_$1_var$2() >---------------------------------------------------*/
-int
-ncmpi_$1_var$2(int                ncid,
-               int                varid,
-               BufConst($1) void *buf,
-               MPI_Offset         bufcount,
-               MPI_Datatype       buftype)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset *start, *count;
-
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VAR,
-                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    GET_FULL_DIMENSIONS(start, count)
-
-    /* $1_var is a special case of $1_varm */
-    status = ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)buf,
-                                bufcount, buftype, ReadWrite($1),
-                                CollIndep($2));
-    NCI_Free(start);
-    return status;
-}
-')dnl
-
-dnl PnetCDF flexible APIs
-VAR_FLEXIBLE(put)
-VAR_FLEXIBLE(get)
-VAR_FLEXIBLE(put, _all)
-VAR_FLEXIBLE(get, _all)
-
-dnl
-dnl VAR(ncid, varid, op)
-dnl
-define(`VAR',dnl
-`dnl
-/*----< ncmpi_$1_var_$3$2() >------------------------------------------------*/
-int
-ncmpi_$1_var_$3$2(int              ncid,
-                  int              varid,
-                  BufConst($1) $4 *op)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset *start, *count;
-
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, API_VAR,
-                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    GET_FULL_DIMENSIONS(start, count)
-
-    /* $1_var is a special case of $1_varm */
-    status = ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)op,
-                                -1, $5, ReadWrite($1), CollIndep($2));
-    NCI_Free(start);
-    return status;
-}
-')dnl
-
-VAR(put,     , text,      char,               MPI_CHAR)
-VAR(put,     , schar,     schar,              MPI_SIGNED_CHAR)
-VAR(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR(put,     , short,     short,              MPI_SHORT)
-VAR(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR(put,     , int,       int,                MPI_INT)
-VAR(put,     , uint,      uint,               MPI_UNSIGNED)
-VAR(put,     , long,      long,               MPI_LONG)
-VAR(put,     , float,     float,              MPI_FLOAT)
-VAR(put,     , double,    double,             MPI_DOUBLE)
-VAR(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VAR(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VAR(put, _all, text,      char,               MPI_CHAR)
-VAR(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VAR(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR(put, _all, short,     short,              MPI_SHORT)
-VAR(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR(put, _all, int,       int,                MPI_INT)
-VAR(put, _all, uint,      uint,               MPI_UNSIGNED)
-VAR(put, _all, long,      long,               MPI_LONG)
-VAR(put, _all, float,     float,              MPI_FLOAT)
-VAR(put, _all, double,    double,             MPI_DOUBLE)
-VAR(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VAR(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VAR(get,     , text,      char,               MPI_CHAR)
-VAR(get,     , schar,     schar,              MPI_SIGNED_CHAR)
-VAR(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR(get,     , short,     short,              MPI_SHORT)
-VAR(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR(get,     , int,       int,                MPI_INT)
-VAR(get,     , uint,      uint,               MPI_UNSIGNED)
-VAR(get,     , long,      long,               MPI_LONG)
-VAR(get,     , float,     float,              MPI_FLOAT)
-VAR(get,     , double,    double,             MPI_DOUBLE)
-VAR(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VAR(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VAR(get, _all, text,      char,               MPI_CHAR)
-VAR(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VAR(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR(get, _all, short,     short,              MPI_SHORT)
-VAR(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR(get, _all, int,       int,                MPI_INT)
-VAR(get, _all, uint,      uint,               MPI_UNSIGNED)
-VAR(get, _all, long,      long,               MPI_LONG)
-VAR(get, _all, float,     float,              MPI_FLOAT)
-VAR(get, _all, double,    double,             MPI_DOUBLE)
-VAR(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VAR(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
+include(`foreach.m4')dnl
+include(`utils.m4')dnl
 dnl
-dnl VAR1_FLEXIBLE
+define(`APINAME',`ifelse(`$3',`',`ncmpi_$1_var$2$4',`ncmpi_$1_var$2_$3$4')')dnl
 dnl
-define(`VAR1_FLEXIBLE',dnl
-`dnl
-/*----< ncmpi_$1_var1$2() >--------------------------------------------------*/
-int
-ncmpi_$1_var1$2(int                ncid,
-                int                varid,
-                const MPI_Offset   start[],
-                BufConst($1) void *buf,
-                MPI_Offset         bufcount,
-                MPI_Datatype       buftype)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset *count;
-
-    status = ncmpii_sanity_check(ncid, varid, start, NULL, bufcount, API_VAR1,
-                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    GET_ONE_COUNT(count)
-
-    status = ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)buf,
-                                bufcount, buftype, ReadWrite($1),
-                                CollIndep($2));
-    NCI_Free(count);
-    return status;
-}
-')dnl
-
-VAR1_FLEXIBLE(put)
-VAR1_FLEXIBLE(get)
-VAR1_FLEXIBLE(put, _all)
-VAR1_FLEXIBLE(get, _all)
-
-dnl
-dnl VAR1
+dnl GETPUT_API(get/put, kind, itype, coll/indep)
 dnl
-define(`VAR1',dnl
+define(`GETPUT_API',dnl
 `dnl
-/*----< ncmpi_$1_var1_$3$2() >-----------------------------------------------*/
+/*----< APINAME($1,$2,$3,$4)() >---------------------------------------------*/
 int
-ncmpi_$1_var1_$3$2(int               ncid,
-                   int               varid,
-                   const MPI_Offset  start[],
-                   BufConst($1) $4  *op)
+APINAME($1,$2,$3,$4)(int ncid, int varid, ArgKind($2) BufArgs($1,$3))
 {
     int         status;
     NC         *ncp;
     NC_var     *varp=NULL;
-    MPI_Offset *count;
-
-    status = ncmpii_sanity_check(ncid, varid, start, NULL, 0, API_VAR1,
-                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    ifelse(`$2', `',  `MPI_Offset *start, *count;',
+           `$2', `1', `MPI_Offset *count;')
+
+    status = ncmpii_sanity_check(ncid, varid, ArgStartCount($2),
+                                 ifelse(`$3', `', `bufcount', `0'),
+                                 ifelse(`$3', `', `buftype',  `ITYPE2MPI($3)'),
+                                 API_KIND($2), ifelse(`$3', `', `1', `0'),
+                                 1, ReadWrite($1),
+                                 CollIndep($4), &ncp, &varp);
     if (status != NC_NOERR) return status;
 
-    GET_ONE_COUNT(count)
+    ifelse(`$2', `',  `GET_FULL_DIMENSIONS(start, count)',
+           `$2', `1', `GET_ONE_COUNT(count)')
 
-    /* $1_var1 is a special case of $1_varm */
-    status = ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)op,
-                                -1, $5, ReadWrite($1), CollIndep($2));
-    NCI_Free(count);
+    /* APINAME($1,$2,$3,$4) is a special case of APINAME($1,m,$3,$4) */
+    status = ncmpii_getput_varm(ncp, varp, start, count, ArgStrideMap($2),
+                                (void*)buf,
+                                ifelse(`$3', `', `bufcount, buftype',
+                                                 `-1, ITYPE2MPI($3)'),
+                                ReadWrite($1), CollIndep($4));
+    ifelse(`$2', `', `NCI_Free(start);', `$2', `1', `NCI_Free(count);')
     return status;
 }
 ')dnl
-
-VAR1(put,     , text,      char,               MPI_CHAR)
-VAR1(put,     , schar,     schar,              MPI_SIGNED_CHAR)
-VAR1(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR1(put,     , short,     short,              MPI_SHORT)
-VAR1(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR1(put,     , int,       int,                MPI_INT)
-VAR1(put,     , uint,      uint,               MPI_UNSIGNED)
-VAR1(put,     , long,      long,               MPI_LONG)
-VAR1(put,     , float,     float,              MPI_FLOAT)
-VAR1(put,     , double,    double,             MPI_DOUBLE)
-VAR1(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VAR1(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VAR1(put, _all, text,      char,               MPI_CHAR)
-VAR1(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VAR1(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR1(put, _all, short,     short,              MPI_SHORT)
-VAR1(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR1(put, _all, int,       int,                MPI_INT)
-VAR1(put, _all, uint,      uint,               MPI_UNSIGNED)
-VAR1(put, _all, long,      long,               MPI_LONG)
-VAR1(put, _all, float,     float,              MPI_FLOAT)
-VAR1(put, _all, double,    double,             MPI_DOUBLE)
-VAR1(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VAR1(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VAR1(get,     , text,      char,               MPI_CHAR)
-VAR1(get,     , schar,     schar,              MPI_SIGNED_CHAR)
-VAR1(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR1(get,     , short,     short,              MPI_SHORT)
-VAR1(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR1(get,     , int,       int,                MPI_INT)
-VAR1(get,     , uint,      uint,               MPI_UNSIGNED)
-VAR1(get,     , long,      long,               MPI_LONG)
-VAR1(get,     , float,     float,              MPI_FLOAT)
-VAR1(get,     , double,    double,             MPI_DOUBLE)
-VAR1(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VAR1(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VAR1(get, _all, text,      char,               MPI_CHAR)
-VAR1(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VAR1(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR1(get, _all, short,     short,              MPI_SHORT)
-VAR1(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR1(get, _all, int,       int,                MPI_INT)
-VAR1(get, _all, uint,      uint,               MPI_UNSIGNED)
-VAR1(get, _all, long,      long,               MPI_LONG)
-VAR1(get, _all, float,     float,              MPI_FLOAT)
-VAR1(get, _all, double,    double,             MPI_DOUBLE)
-VAR1(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VAR1(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-dnl
-dnl VARA_FLEXIBLE
 dnl
-define(`VARA_FLEXIBLE',dnl
-`dnl
-/*----< ncmpi_$1_vara$2() >--------------------------------------------------*/
-int
-ncmpi_$1_vara$2(int                ncid,
-                int                varid,
-                const MPI_Offset   start[],
-                const MPI_Offset   count[],
-                BufConst($1) void *buf,
-                MPI_Offset         bufcount,
-                MPI_Datatype       buftype)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARA,
-                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    /* $1_vara is a special case of $1_varm */
-    return ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)buf,
-                              bufcount, buftype, ReadWrite($1), CollIndep($2));
-}
-')dnl
-
-dnl PnetCDF flexible APIs
-VARA_FLEXIBLE(put)
-VARA_FLEXIBLE(get)
-VARA_FLEXIBLE(put, _all)
-VARA_FLEXIBLE(get, _all)
-
-dnl
-dnl VARA
-dnl
-define(`VARA',dnl
-`dnl
-/*----< ncmpi_$1_vara_$3$2() >-----------------------------------------------*/
-int
-ncmpi_$1_vara_$3$2(int               ncid,
-                   int               varid,
-                   const MPI_Offset  start[],
-                   const MPI_Offset  count[],
-                   BufConst($1) $4  *op)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARA,
-                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    /* $1_vara is a special case of $1_varm */
-    return ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)op,
-                              -1, $5, ReadWrite($1), CollIndep($2));
-}
-')dnl
-
-VARA(put,     , text,      char,               MPI_CHAR)
-VARA(put,     , schar,     schar,              MPI_SIGNED_CHAR)
-VARA(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARA(put,     , short,     short,              MPI_SHORT)
-VARA(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARA(put,     , int,       int,                MPI_INT)
-VARA(put,     , uint,      uint,               MPI_UNSIGNED)
-VARA(put,     , long,      long,               MPI_LONG)
-VARA(put,     , float,     float,              MPI_FLOAT)
-VARA(put,     , double,    double,             MPI_DOUBLE)
-VARA(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VARA(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARA(put, _all, text,      char,               MPI_CHAR)
-VARA(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VARA(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARA(put, _all, short,     short,              MPI_SHORT)
-VARA(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARA(put, _all, int,       int,                MPI_INT)
-VARA(put, _all, uint,      uint,               MPI_UNSIGNED)
-VARA(put, _all, long,      long,               MPI_LONG)
-VARA(put, _all, float,     float,              MPI_FLOAT)
-VARA(put, _all, double,    double,             MPI_DOUBLE)
-VARA(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VARA(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARA(get,     , text,      char,               MPI_CHAR)
-VARA(get,     , schar,     schar,              MPI_SIGNED_CHAR)
-VARA(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARA(get,     , short,     short,              MPI_SHORT)
-VARA(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARA(get,     , int,       int,                MPI_INT)
-VARA(get,     , uint,      uint,               MPI_UNSIGNED)
-VARA(get,     , long,      long,               MPI_LONG)
-VARA(get,     , float,     float,              MPI_FLOAT)
-VARA(get,     , double,    double,             MPI_DOUBLE)
-VARA(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VARA(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARA(get, _all, text,      char,               MPI_CHAR)
-VARA(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VARA(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARA(get, _all, short,     short,              MPI_SHORT)
-VARA(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARA(get, _all, int,       int,                MPI_INT)
-VARA(get, _all, uint,      uint,               MPI_UNSIGNED)
-VARA(get, _all, long,      long,               MPI_LONG)
-VARA(get, _all, float,     float,              MPI_FLOAT)
-VARA(get, _all, double,    double,             MPI_DOUBLE)
-VARA(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VARA(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-dnl
-dnl VARS_FLEXIBLE
-dnl
-define(`VARS_FLEXIBLE',dnl
-`dnl
-/*----< ncmpi_$1_vars$2() >--------------------------------------------------*/
-int
-ncmpi_$1_vars$2(int                ncid,
-                int                varid,
-                const MPI_Offset   start[],
-                const MPI_Offset   count[],
-                const MPI_Offset   stride[],
-                BufConst($1) void *buf,
-                MPI_Offset         bufcount,
-                MPI_Datatype       buftype)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARS,
-                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    return ncmpii_getput_varm(ncp, varp, start, count, stride, NULL, (void*)buf,
-                              bufcount, buftype, ReadWrite($1), CollIndep($2));
-}
-')dnl
-
-dnl PnetCDF flexible APIs
-VARS_FLEXIBLE(put)
-VARS_FLEXIBLE(get)
-VARS_FLEXIBLE(put, _all)
-VARS_FLEXIBLE(get, _all)
-
-dnl
-dnl VARS
-dnl
-define(`VARS',dnl
-`dnl
-/*----< ncmpi_$1_vars_$3$2() >-----------------------------------------------*/
-int
-ncmpi_$1_vars_$3$2(int               ncid,
-                   int               varid,
-                   const MPI_Offset  start[],
-                   const MPI_Offset  count[],
-                   const MPI_Offset  stride[],
-                   BufConst($1) $4  *op)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARS,
-                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    return ncmpii_getput_varm(ncp, varp, start, count, stride, NULL, (void*)op,
-                              -1, $5, ReadWrite($1), CollIndep($2));
-}
-')dnl
-
-VARS(put,     , text,      char,               MPI_CHAR)
-VARS(put,     , schar,     schar,              MPI_SIGNED_CHAR)
-VARS(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARS(put,     , short,     short,              MPI_SHORT)
-VARS(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARS(put,     , int,       int,                MPI_INT)
-VARS(put,     , uint,      uint,               MPI_UNSIGNED)
-VARS(put,     , long,      long,               MPI_LONG)
-VARS(put,     , float,     float,              MPI_FLOAT)
-VARS(put,     , double,    double,             MPI_DOUBLE)
-VARS(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VARS(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARS(put, _all, text,      char,               MPI_CHAR)
-VARS(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VARS(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARS(put, _all, short,     short,              MPI_SHORT)
-VARS(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARS(put, _all, int,       int,                MPI_INT)
-VARS(put, _all, uint,      uint,               MPI_UNSIGNED)
-VARS(put, _all, long,      long,               MPI_LONG)
-VARS(put, _all, float,     float,              MPI_FLOAT)
-VARS(put, _all, double,    double,             MPI_DOUBLE)
-VARS(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VARS(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARS(get,     , text,      char,               MPI_CHAR)
-VARS(get,     , schar,     schar,              MPI_SIGNED_CHAR)
-VARS(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARS(get,     , short,     short,              MPI_SHORT)
-VARS(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARS(get,     , int,       int,                MPI_INT)
-VARS(get,     , uint,      uint,               MPI_UNSIGNED)
-VARS(get,     , long,      long,               MPI_LONG)
-VARS(get,     , float,     float,              MPI_FLOAT)
-VARS(get,     , double,    double,             MPI_DOUBLE)
-VARS(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VARS(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARS(get, _all, text,      char,               MPI_CHAR)
-VARS(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VARS(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARS(get, _all, short,     short,              MPI_SHORT)
-VARS(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARS(get, _all, int,       int,                MPI_INT)
-VARS(get, _all, uint,      uint,               MPI_UNSIGNED)
-VARS(get, _all, long,      long,               MPI_LONG)
-VARS(get, _all, float,     float,              MPI_FLOAT)
-VARS(get, _all, double,    double,             MPI_DOUBLE)
-VARS(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VARS(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-dnl
-dnl VARM_FLEXIBLE
-dnl
-define(`VARM_FLEXIBLE',dnl
-`dnl
-/*----< ncmpi_$1_varm$2() >--------------------------------------------------*/
-int
-ncmpi_$1_varm$2(int                ncid,
-                int                varid,
-                const MPI_Offset   start[],
-                const MPI_Offset   count[],
-                const MPI_Offset   stride[],
-                const MPI_Offset   imap[],
-                BufConst($1) void *buf,
-                MPI_Offset         bufcount,
-                MPI_Datatype       buftype)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARM,
-                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    return ncmpii_getput_varm(ncp, varp, start, count, stride, imap,
-                              (void*)buf, bufcount, buftype, ReadWrite($1),
-                              CollIndep($2));
-}
-')dnl
-
-dnl PnetCDF flexible APIs
-VARM_FLEXIBLE(put)
-VARM_FLEXIBLE(get)
-VARM_FLEXIBLE(put, _all)
-VARM_FLEXIBLE(get, _all)
-
-dnl
-dnl VARM
-dnl
-define(`VARM',dnl
-`dnl
-/*----< ncmpi_$1_varm_$3$2() >------------------------------------------------*/
-int
-ncmpi_$1_varm_$3$2(int               ncid,
-                   int               varid,
-                   const MPI_Offset  start[],
-                   const MPI_Offset  count[],
-                   const MPI_Offset  stride[],
-                   const MPI_Offset  imap[],
-                   BufConst($1) $4  *op)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARM,
-                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    return ncmpii_getput_varm(ncp, varp, start, count, stride, imap, (void*)op,
-                              -1, $5, ReadWrite($1), CollIndep($2));
-}
-')dnl
-
-VARM(put,     , text,      char,               MPI_CHAR)
-VARM(put,     , schar,     schar,              MPI_SIGNED_CHAR)
-VARM(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARM(put,     , short,     short,              MPI_SHORT)
-VARM(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARM(put,     , int,       int,                MPI_INT)
-VARM(put,     , uint,      uint,               MPI_UNSIGNED)
-VARM(put,     , long,      long,               MPI_LONG)
-VARM(put,     , float,     float,              MPI_FLOAT)
-VARM(put,     , double,    double,             MPI_DOUBLE)
-VARM(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VARM(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARM(put, _all, text,      char,               MPI_CHAR)
-VARM(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VARM(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARM(put, _all, short,     short,              MPI_SHORT)
-VARM(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARM(put, _all, int,       int,                MPI_INT)
-VARM(put, _all, uint,      uint,               MPI_UNSIGNED)
-VARM(put, _all, long,      long,               MPI_LONG)
-VARM(put, _all, float,     float,              MPI_FLOAT)
-VARM(put, _all, double,    double,             MPI_DOUBLE)
-VARM(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VARM(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARM(get,     , text,      char,               MPI_CHAR)
-VARM(get,     , schar,     schar,              MPI_SIGNED_CHAR)
-VARM(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARM(get,     , short,     short,              MPI_SHORT)
-VARM(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARM(get,     , int,       int,                MPI_INT)
-VARM(get,     , uint,      uint,               MPI_UNSIGNED)
-VARM(get,     , long,      long,               MPI_LONG)
-VARM(get,     , float,     float,              MPI_FLOAT)
-VARM(get,     , double,    double,             MPI_DOUBLE)
-VARM(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VARM(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARM(get, _all, text,      char,               MPI_CHAR)
-VARM(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VARM(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARM(get, _all, short,     short,              MPI_SHORT)
-VARM(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARM(get, _all, int,       int,                MPI_INT)
-VARM(get, _all, uint,      uint,               MPI_UNSIGNED)
-VARM(get, _all, long,      long,               MPI_LONG)
-VARM(get, _all, float,     float,              MPI_FLOAT)
-VARM(get, _all, double,    double,             MPI_DOUBLE)
-VARM(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VARM(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-
+/*---- PnetCDF flexible APIs ------------------------------------------------*/
+foreach(`kind', (, 1, a, s, m),
+        `foreach(`putget', (put, get),
+                 `foreach(`collindep', (, _all),
+                          `GETPUT_API(putget,kind,,collindep)'
+)')')
+
+/*---- PnetCDF high-level APIs ----------------------------------------------*/
+foreach(`kind', (, 1, a, s, m),
+        `foreach(`putget', (put, get),
+                 `foreach(`collindep', (, _all),
+                          `foreach(`itype', (ITYPE_LIST),
+                                   `GETPUT_API(putget,kind,itype,collindep)'
+)')')')
diff --git a/src/lib/hash_func.c b/src/lib/hash_func.c
new file mode 100644
index 0000000..cc73682
--- /dev/null
+++ b/src/lib/hash_func.c
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (C) 2016, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: hash_func.c 2589 2016-10-30 17:42:43Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include <ncconfig.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h> /* strlen() */
+
+#include "nc.h"
+
+/* borrow Jenkins hash function:
+ * https://en.wikipedia.org/wiki/Jenkins_hash_function
+ */
+int ncmpii_jenkins_one_at_a_time_hash(const char *str_name)
+{
+    unsigned int i, hash=0;
+    for (i=0; i<strlen(str_name); ++i) {
+        hash += (unsigned int)str_name[i];
+        hash += (hash << 10);
+        hash ^= (hash >> 6);
+    }
+    hash += (hash << 3);
+    hash ^= (hash >> 11);
+    hash += (hash << 15);
+
+#if 0
+    ret = (int)hash; /* the return value will be used as an array index */
+    return ((ret < 0) ? -ret : ret); /* make the value positive */
+#endif
+    /* this is to avoid expensive % operation, i.e. % HASH_TABLE_SIZE
+    return (int)((hash ^ (hash>>10) ^ (hash>>20)) & (HASH_TABLE_SIZE-1));
+    */
+    return (int)(hash & (HASH_TABLE_SIZE-1));
+    /* return value will be used as an array index */
+}
+
+/* try different hash functions described in
+ * http://www.burtleburtle.net/bob/hash/doobs.html
+ */
+int ncmpii_additive_hash(const char *str_name)
+{
+    size_t i, len = strlen(str_name);
+    int hash = (int)len;
+    for (i=0; i<len; ++i)
+        hash += str_name[i]; /* additive hash */
+
+    return (hash % 251); /* 251 is the largest prime <= 255 */
+}
+
+int ncmpii_rotating_hash(const char *str_name)
+{
+    size_t i, len = strlen(str_name);
+    unsigned int hash = (unsigned int)len;
+    for (i=0; i<len; ++i)
+        hash = (hash<<4)^(hash>>28)^(unsigned int)str_name[i];
+
+    /* below is a clever way to replace (hash % prime) */
+    return (int)((hash ^ (hash>>10) ^ (hash>>20)) & (HASH_TABLE_SIZE-1));
+}
+
+int ncmpii_Bernstein_hash(const char *str_name)
+{
+    size_t i, len = strlen(str_name);
+    unsigned int hash = (unsigned int)len;
+    for (i=0; i<len; ++i)
+        /* hash = 65*hash+str_name[i]; */
+        hash = hash+(hash<<6)+(unsigned int)str_name[i];
+
+    return (int)((hash ^ (hash>>10) ^ (hash>>20)) & (HASH_TABLE_SIZE-1));
+}
+
+int ncmpii_Pearson_hash(const char *str_name)
+{
+#if HASH_TABLE_SIZE == 256
+    unsigned char T[256] = {
+        251, 175, 119, 215, 81, 14, 79, 191, 103, 49, 181, 143, 186, 157,  0,
+        232, 31, 32, 55, 60, 152, 58, 17, 237, 174, 70, 160, 144, 220, 90, 57,
+        223, 59,  3, 18, 140, 111, 166, 203, 196, 134, 243, 124, 95, 222, 179,
+        197, 65, 180, 48, 36, 15, 107, 46, 233, 130, 165, 30, 123, 161, 209, 23,
+        97, 16, 40, 91, 219, 61, 100, 10, 210, 109, 250, 127, 22, 138, 29, 108,
+        244, 67, 207,  9, 178, 204, 74, 98, 126, 249, 167, 116, 34, 77, 193,
+        200, 121,  5, 20, 113, 71, 35, 128, 13, 182, 94, 25, 226, 227, 199, 75,
+        27, 41, 245, 230, 224, 43, 225, 177, 26, 155, 150, 212, 142, 218, 115,
+        241, 73, 88, 105, 39, 114, 62, 255, 192, 201, 145, 214, 168, 158, 221,
+        148, 154, 122, 12, 84, 82, 163, 44, 139, 228, 236, 205, 242, 217, 11,
+        187, 146, 159, 64, 86, 239, 195, 42, 106, 198, 118, 112, 184, 172, 87,
+        2, 173, 117, 176, 229, 247, 253, 137, 185, 99, 164, 102, 147, 45, 66,
+        231, 52, 141, 211, 194, 206, 246, 238, 56, 110, 78, 248, 63, 240, 189,
+        93, 92, 51, 53, 183, 19, 171, 72, 50, 33, 104, 101, 69, 8, 252, 83, 120,
+        76, 135, 85, 54, 202, 125, 188, 213, 96, 235, 136, 208, 162, 129, 190,
+        132, 156, 38, 47, 1, 7, 254, 24, 4, 216, 131, 89, 21, 28, 133, 37, 153,
+        149, 80, 170, 68, 6, 169, 234, 151
+    };
+    size_t i, len=strlen(str_name);
+    unsigned char hash = (unsigned char)len;
+    for (i=len; i>0; ) hash = T[hash ^ str_name[--i]];
+    return (int)hash;
+#else
+    unsigned int i, hash=strlen(str_name);
+    for (i=0; i<strlen(str_name); ++i)
+        hash ^= str_name[i];
+
+    return (int)((hash ^ (hash>>10) ^ (hash>>20)) & (HASH_TABLE_SIZE-1));
+#endif
+}
+
diff --git a/src/lib/header.c b/src/lib/header.c
index 06101fd..941bea7 100644
--- a/src/lib/header.c
+++ b/src/lib/header.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: header.c 2322 2016-02-26 22:47:06Z wkliao $ */
+/* $Id: header.c 2590 2016-10-31 21:37:02Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <assert.h>
@@ -61,9 +61,9 @@ static int hdr_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap);
 /*
  * "magic number" at beginning of file: 0x43444601 (big endian)
  */
-static const schar ncmagic1[] = {'C', 'D', 'F', 0x01};
-static const schar ncmagic2[] = {'C', 'D', 'F', 0x02};
-static const schar ncmagic5[] = {'C', 'D', 'F', 0x05};
+static const char ncmagic1[] = {'C', 'D', 'F', 0x01};
+static const char ncmagic2[] = {'C', 'D', 'F', 0x02};
+static const char ncmagic5[] = {'C', 'D', 'F', 0x05};
 
 /*
  * Recompute the shapes of all variables
@@ -90,7 +90,7 @@ ncmpii_NC_computeshapes(NC *ncp)
 
     for ( /*NADA*/; vpp < end; vpp++) {
         /* (*vpp)->len is recomputed from dimensions in ncmpii_NC_var_shape64() */
-        status = ncmpii_NC_var_shape64(ncp, *vpp, &ncp->dims);
+        status = ncmpii_NC_var_shape64(*vpp, &ncp->dims);
 
         if (status != NC_NOERR) return status ;
 
@@ -386,11 +386,11 @@ ncmpii_hdr_len_NC(const NC *ncp)
 
     assert(ncp != NULL);
 
-    if (fIsSet(ncp->flags, NC_64BIT_DATA)) {        /* CDF-5 */
+    if (ncp->format == 5) {        /* CDF-5 */
         sizeof_t     = X_SIZEOF_INT64; /* 8-byte integer for all integers */
         sizeof_off_t = X_SIZEOF_INT64; /* 8-byte integer for var begin */
     }
-    else if (fIsSet(ncp->flags, NC_64BIT_OFFSET)) { /* CDF-2 */
+    else if (ncp->format == 2) { /* CDF-2 */
         sizeof_t     = X_SIZEOF_INT; /* 4-byte integer in CDF-1 */
         sizeof_off_t = X_SIZEOF_INT64; /* 8-byte integer for var begin */
     }
@@ -430,7 +430,7 @@ hdr_put_NC_name(bufferinfo      *pbp,
 
     /* copy nelems */
     if (pbp->version == 5)
-        status = ncmpix_put_uint64((void**)(&pbp->pos), ncstrp->nchars);
+        status = ncmpix_put_uint64((void**)(&pbp->pos), (uint64)ncstrp->nchars);
     else {
         if (ncstrp->nchars != (uint)ncstrp->nchars) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
         status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)ncstrp->nchars);
@@ -505,7 +505,7 @@ hdr_put_NC_dim(bufferinfo   *pbp,
 
     /* copy dim_length */
     if (pbp->version == 5)
-        status = ncmpix_put_uint64((void**)(&pbp->pos), dimp->size);
+        status = ncmpix_put_uint64((void**)(&pbp->pos), (uint64)dimp->size);
     else {
         /* TODO: Isn't checking dimension size already done in def_dim()? */
         if (dimp->size != (uint)dimp->size) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
@@ -555,9 +555,9 @@ hdr_put_NC_dimarray(bufferinfo        *pbp,
 
         /* copy nelems */
         if (pbp->version == 5)
-            status = ncmpix_put_uint64((void**)(&pbp->pos), ncap->ndefined);
+            status = ncmpix_put_uint64((void**)(&pbp->pos), (uint64)ncap->ndefined);
         else
-            status = ncmpix_put_uint32((void**)(&pbp->pos), ncap->ndefined);
+            status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)ncap->ndefined);
         if (status != NC_NOERR) return status;
 
         /* copy [dim ...] */
@@ -590,12 +590,12 @@ hdr_put_NC_attr(bufferinfo    *pbp,
     if (status != NC_NOERR) return status;
 
     /* copy nc_type */
-    status = ncmpix_put_uint32((void**)(&pbp->pos), attrp->type);
+    status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)attrp->type);
     if (status != NC_NOERR) return status;
 
     /* copy nelems */
     if (pbp->version == 5)
-        status = ncmpix_put_uint64((void**)(&pbp->pos), attrp->nelems);
+        status = ncmpix_put_uint64((void**)(&pbp->pos), (uint64)attrp->nelems);
     else {
         if (attrp->nelems != (uint)attrp->nelems) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
         status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)attrp->nelems);
@@ -648,9 +648,9 @@ hdr_put_NC_attrarray(bufferinfo         *pbp,
 
         /* copy nelems */
         if (pbp->version == 5)
-            status = ncmpix_put_uint64((void**)(&pbp->pos), ncap->ndefined);
+            status = ncmpix_put_uint64((void**)(&pbp->pos), (uint64)ncap->ndefined);
         else
-            status = ncmpix_put_uint32((void**)(&pbp->pos), ncap->ndefined);
+            status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)ncap->ndefined);
         if (status != NC_NOERR) return status;
 
         /* copy [attr ...] */
@@ -692,17 +692,17 @@ hdr_put_NC_var(bufferinfo   *pbp,
 
     /* copy nelems */
     if (pbp->version == 5)
-        status = ncmpix_put_uint64((void**)(&pbp->pos), varp->ndims);
+        status = ncmpix_put_uint64((void**)(&pbp->pos), (uint64)varp->ndims);
     else
-        status = ncmpix_put_uint32((void**)(&pbp->pos), varp->ndims);
+        status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)varp->ndims);
     if (status != NC_NOERR) return status;
 
     /* copy [dimid ...] */
     for (i=0; i<varp->ndims; i++) {
         if (pbp->version == 5)
-            status = ncmpix_put_uint64((void**)(&pbp->pos), varp->dimids[i]);
+            status = ncmpix_put_uint64((void**)(&pbp->pos), (uint64)varp->dimids[i]);
         else
-            status = ncmpix_put_uint32((void**)(&pbp->pos), varp->dimids[i]);
+            status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)varp->dimids[i]);
         if (status != NC_NOERR) return status;
     }
 
@@ -711,7 +711,7 @@ hdr_put_NC_var(bufferinfo   *pbp,
     if (status != NC_NOERR) return status;
 
     /* copy nc_type */
-    status = ncmpix_put_uint32((void**)(&pbp->pos), varp->type);
+    status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)varp->type);
     if (status != NC_NOERR) return status;
 
     /* copy vsize */
@@ -719,7 +719,7 @@ hdr_put_NC_var(bufferinfo   *pbp,
      * in CDF-5, it is a 64-bit integer
      */
     if (pbp->version == 5)
-        status = ncmpix_put_uint64((void**)(&pbp->pos), varp->len);
+        status = ncmpix_put_uint64((void**)(&pbp->pos), (uint64)varp->len);
     else {
         /* Special case, when there is no record variable, the last fixed-size
          * variable can be larger than 2 GiB if its file starting offset is
@@ -741,7 +741,7 @@ hdr_put_NC_var(bufferinfo   *pbp,
         status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)varp->begin);
     }
     else
-        status = ncmpix_put_uint64((void**)(&pbp->pos), varp->begin);
+        status = ncmpix_put_uint64((void**)(&pbp->pos), (uint64)varp->begin);
     if (status != NC_NOERR) return status;
 
     return NC_NOERR;
@@ -788,9 +788,9 @@ hdr_put_NC_vararray(bufferinfo        *pbp,
 
         /* copy nelems */
         if (pbp->version == 5)
-            status = ncmpix_put_uint64((void**)(&pbp->pos), ncap->ndefined);
+            status = ncmpix_put_uint64((void**)(&pbp->pos), (uint64)ncap->ndefined);
         else
-            status = ncmpix_put_uint32((void**)(&pbp->pos), ncap->ndefined);
+            status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)ncap->ndefined);
         if (status != NC_NOERR) return status;
 
         /* copy [var ...] */
@@ -818,8 +818,6 @@ ncmpii_hdr_put_NC(NC   *ncp,
     putbuf.pos       = buf;
     putbuf.base      = buf;
     putbuf.size      = ncp->xsz;
-    putbuf.put_size  = 0;
-    putbuf.get_size  = 0;
     putbuf.safe_mode = ncp->safe_mode;
 
     /* netCDF file format:
@@ -828,28 +826,29 @@ ncmpii_hdr_put_NC(NC   *ncp,
      */
 
     /* copy "magic", 4 characters */
-    if (ncp->flags & NC_64BIT_DATA) {
+    if (ncp->format == 5) {
         putbuf.version = 5;
-        status = ncmpix_putn_schar_schar(&putbuf.pos, sizeof(ncmagic5), ncmagic5);
+        status = ncmpix_putn_text(&putbuf.pos, sizeof(ncmagic5), ncmagic5);
     }
-    else if (ncp->flags & NC_64BIT_OFFSET) {
+    else if (ncp->format == 2) {
         putbuf.version = 2;
-        status = ncmpix_putn_schar_schar(&putbuf.pos, sizeof(ncmagic2), ncmagic2);
+        status = ncmpix_putn_text(&putbuf.pos, sizeof(ncmagic2), ncmagic2);
     }
     else {
         putbuf.version = 1;
-        status = ncmpix_putn_schar_schar(&putbuf.pos, sizeof(ncmagic1), ncmagic1);
+        status = ncmpix_putn_text(&putbuf.pos, sizeof(ncmagic1), ncmagic1);
     }
     if (status != NC_NOERR) return status;
 
     /* copy numrecs, number of records */
     nrecs = ncp->numrecs;
-    if (ncp->flags & NC_64BIT_DATA)
-        status = ncmpix_put_uint64((void**)(&putbuf.pos), nrecs);
-    else {
+    if (ncp->format < 5) {
         if (nrecs != (uint)nrecs) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
         status = ncmpix_put_uint32((void**)(&putbuf.pos), (uint)nrecs);
     }
+    else {
+        status = ncmpix_put_uint64((void**)(&putbuf.pos), (uint64)nrecs);
+    }
     if (status != NC_NOERR) return status;
 
     /* copy dim_list */
@@ -864,9 +863,6 @@ ncmpii_hdr_put_NC(NC   *ncp,
     status = hdr_put_NC_vararray(&putbuf, &ncp->vars);
     if (status != NC_NOERR) return status;
 
-    ncp->nciop->put_size += putbuf.put_size;
-    ncp->nciop->get_size += putbuf.get_size;
-
     return NC_NOERR;
 }
 
@@ -906,7 +902,6 @@ hdr_fetch(bufferinfo *gbp) {
      * all data in the buffer has been consumed */
     if (slack == gbp->size) slack = 0;
 
-    if (gbp->size != (size_t)gbp->size) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
     if (gbp->size != (int)gbp->size) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
 
     memset(gbp->base, 0, (size_t)gbp->size);
@@ -926,9 +921,9 @@ hdr_fetch(bufferinfo *gbp) {
             if (err == NC_EFILE) DEBUG_ASSIGN_ERROR(err, NC_EREAD)
         }
         else {
-            int get_size;
+            int get_size; /* actual read amount can be smaller */
             MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
-            gbp->get_size += get_size;
+            gbp->nciop->get_size += get_size;
         }
     }
     /* we might have had to backtrack */
@@ -939,7 +934,7 @@ hdr_fetch(bufferinfo *gbp) {
         if (err != NC_NOERR) return err;
     }
 
-    /* broadcast root's read to other processes */
+    /* broadcast root's read (full or partial header) to other processes */
     TRACE_COMM(MPI_Bcast)(gbp->base, (int)gbp->size, MPI_BYTE, 0, gbp->nciop->comm);
 
     return err;
@@ -1054,20 +1049,21 @@ hdr_get_nc_type(bufferinfo *gbp,
 }
 
 /*----< ncmpix_len_nctype() >------------------------------------------------*/
+/* return the length of external data type */
 int
 ncmpix_len_nctype(nc_type type) {
     switch(type) {
         case NC_BYTE:
         case NC_CHAR:
         case NC_UBYTE:  return X_SIZEOF_CHAR;
-        case NC_SHORT:
-        case NC_USHORT: return X_SIZEOF_SHORT;
-        case NC_INT:
-        case NC_UINT:   return X_SIZEOF_INT;
+        case NC_SHORT:  return X_SIZEOF_SHORT;
+        case NC_USHORT: return X_SIZEOF_USHORT;
+        case NC_INT:    return X_SIZEOF_INT;
+        case NC_UINT:   return X_SIZEOF_UINT;
         case NC_FLOAT:  return X_SIZEOF_FLOAT;
         case NC_DOUBLE: return X_SIZEOF_DOUBLE;
-        case NC_INT64:
-        case NC_UINT64: return X_SIZEOF_INT64;
+        case NC_INT64:  return X_SIZEOF_INT64;
+        case NC_UINT64: return X_SIZEOF_UINT64;
         default: fprintf(stderr,"ncmpix_len_nctype bad type %d\n",type);
                  assert(0);
     }
@@ -1252,6 +1248,8 @@ hdr_get_NC_dimarray(bufferinfo  *gbp,
     /* TODO: we should allow ndefined > 2^32, considering change the data type
      * of ndefined from int to MPI_Offset */
 
+    ncap->unlimited_id = -1;
+
     if (ndefined == 0) {
         if (type != NC_DIMENSION && type != NC_UNSPECIFIED)
             DEBUG_RETURN_ERROR(NC_EINVAL)
@@ -1271,6 +1269,8 @@ hdr_get_NC_dimarray(bufferinfo  *gbp,
                 ncmpii_free_NC_dimarray(ncap);
                 return status;
             }
+            if (ncap->value[i]->size == NC_UNLIMITED)
+                ncap->unlimited_id = i; /* ID of unlimited dimension */
         }
     }
 
@@ -1716,7 +1716,7 @@ ncmpii_hdr_get_NC(NC *ncp)
 {
     int status;
     bufferinfo getbuf;
-    schar magic[sizeof(ncmagic1)];
+    char magic[sizeof(ncmagic1)];
     MPI_Offset nrecs = 0;
     MPI_Aint pos_addr, base_addr;
 
@@ -1725,8 +1725,6 @@ ncmpii_hdr_get_NC(NC *ncp)
     /* Initialize the get buffer that stores the header read from the file */
     getbuf.nciop     = ncp->nciop;
     getbuf.offset    = 0;   /* read from start of the file */
-    getbuf.put_size  = 0;   /* amount of writes so far in bytes */
-    getbuf.get_size  = 0;   /* amount of reads  so far in bytes */
     getbuf.safe_mode = ncp->safe_mode;
 
     /* CDF-5's minimum header size is 4 bytes more than CDF-1 and CDF-2's */
@@ -1746,38 +1744,50 @@ ncmpii_hdr_get_NC(NC *ncp)
 
     /* First get the file format information, magic */
     memset(magic, 0, sizeof(magic));
-    status = ncmpix_getn_schar_schar((const void **)(&getbuf.pos),
-                                     sizeof(magic), magic);
+    status = ncmpix_getn_text((const void **)(&getbuf.pos), sizeof(magic),
+                              magic);
     if (status != NC_NOERR) return status;
     getbuf.index += (MPI_Offset)sizeof(magic);
 
-    /* don't need to worry about CDF-1 or CDF-2
-     * if the first bits are not 'CDF'
-     */
+    /* check if the first three bytes are 'C','D','F' */
     if (memcmp(magic, ncmagic1, sizeof(ncmagic1)-1) != 0) {
+        /* check if is HDF5 file */
+        char signature[8], *hdf5_signature="\211HDF\r\n\032\n";
+        memcpy(signature, magic, 4);
+        ncmpix_getn_text((const void **)(&getbuf.pos), 4, signature+4);
+        if (memcmp(signature, hdf5_signature, 8) == 0) {
+            DEBUG_ASSIGN_ERROR(status, NC_ENOTNC3)
+            if (ncp->safe_mode)
+                fprintf(stderr,"Error: file %s is HDF5 format\n",ncp->nciop->path);
+        }
+        else
+            DEBUG_ASSIGN_ERROR(status, NC_ENOTNC)
         NCI_Free(getbuf.base);
-        DEBUG_RETURN_ERROR(NC_ENOTNC)
+        return status;
     }
 
     /* check version number in last byte of magic */
     if (magic[sizeof(ncmagic1)-1] == 0x1) {
         getbuf.version = 1;
         fSet(ncp->flags, NC_32BIT);
+        ncp->format = 1;
     } else if (magic[sizeof(ncmagic1)-1] == 0x2) {
         getbuf.version = 2;
         fSet(ncp->flags, NC_64BIT_OFFSET);
+        ncp->format = 2;
 #if SIZEOF_MPI_OFFSET < 8
-            /* take the easy way out: if we can't support all CDF-2
-             * files, return immediately */
-            NCI_Free(getbuf.base);
-            DEBUG_RETURN_ERROR(NC_ESMALL)
+        /* take the easy way out: if we can't support all CDF-2
+         * files, return immediately */
+        NCI_Free(getbuf.base);
+        DEBUG_RETURN_ERROR(NC_ESMALL)
 #endif
     } else if (magic[sizeof(ncmagic1)-1] == 0x5) {
         getbuf.version = 5;
         fSet(ncp->flags, NC_64BIT_DATA);
+        ncp->format = 5;
 #if SIZEOF_MPI_OFFSET < 8
-            NCI_Free(getbuf.base);
-            DEBUG_RETURN_ERROR(NC_ESMALL)
+        NCI_Free(getbuf.base);
+        DEBUG_RETURN_ERROR(NC_ESMALL)
 #endif
     } else {
         NCI_Free(getbuf.base);
@@ -1855,9 +1865,6 @@ ncmpii_hdr_get_NC(NC *ncp)
 
     NCI_Free(getbuf.base);
 
-    ncp->nciop->put_size += getbuf.put_size;
-    ncp->nciop->get_size += getbuf.get_size;
-
     return status;
 }
 
@@ -1935,6 +1942,30 @@ ncmpii_comp_dims(int          safe_mode,
 
     local_dim->ndefined = root_dim->ndefined;
 
+#ifndef SEARCH_NAME_LINEARLY
+    if (status != NC_NOERR) {
+        /* dims are not consistent, must rebuild dim name lookup table */
+        for (i=0; i<HASH_TABLE_SIZE; i++) {
+            if (local_dim->nameT[i].num > 0)
+                NCI_Free(local_dim->nameT[i].list);
+            local_dim->nameT[i].num = 0;
+            local_dim->nameT[i].list = NULL;
+        }
+
+        /* populate dim name lookup table */
+        for (i=0; i<local_dim->ndefined; i++) {
+            /* hash the dim name into a key for name lookup */
+            int key = HASH_FUNC(local_dim->value[i]->name->cp);
+            NC_nametable *nameT = &local_dim->nameT[key];
+            if (nameT->num % NC_NAME_TABLE_CHUNK == 0)
+                nameT->list = (int*) NCI_Realloc(nameT->list,
+                              (size_t)(nameT->num+NC_NAME_TABLE_CHUNK) * sizeof(int));
+            nameT->list[nameT->num] = i;
+            nameT->num++;
+        }
+    }
+#endif
+
     return status;
 }
 
@@ -2086,8 +2117,10 @@ ncmpii_comp_attrs(int           safe_mode,
             for (j=0; j<v1->nelems; j++) {
                 /* floating-point inequality here but we genuinely do
                  * expect all processors to set bit-for-bit identical
-                 * headers */
+                 * headers
                 if (fa[j] != fb[j]) {
+                 */
+                if (memcmp(fa+j, fb+j, sizeof(float))) {
                     msg = "%s attribute \"%s\"[%d] FLOAT (root=%f, local=%f)\n";
                     ATTR_WARN_J(msg, name, j, fa[j], fb[j])
                     DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
@@ -2101,8 +2134,10 @@ ncmpii_comp_attrs(int           safe_mode,
             for (j=0; j<v1->nelems; j++) {
                 /* floating-point inequality here but we genuinely do
                  * expect all processors to set bit-for-bit identical
-                 * headers */
+                 * headers
                 if (da[j] != db[j]) {
+                 */
+                if (memcmp(da+j, db+j, sizeof(double))) {
                     msg = "%s attribute \"%s\"[%d] DOUBLE (root=%f, local=%f)\n";
                     ATTR_WARN_J(msg, name, j, da[j], db[j])
                     DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
@@ -2254,6 +2289,30 @@ ncmpii_comp_vars(int          safe_mode,
 
     local_var->ndefined = root_var->ndefined;
 
+#ifndef SEARCH_NAME_LINEARLY
+    if (status != NC_NOERR) {
+        /* vars are not consistent, must rebuild var name lookup table */
+        for (i=0; i<HASH_TABLE_SIZE; i++) {
+            if (local_var->nameT[i].num > 0)
+                NCI_Free(local_var->nameT[i].list);
+            local_var->nameT[i].num = 0;
+            local_var->nameT[i].list = NULL;
+        }
+
+        /* populate var name lookup table */
+        for (i=0; i<local_var->ndefined; i++) {
+            /* hash the var name into a key for name lookup */
+            int key = HASH_FUNC(local_var->value[i]->name->cp);
+            NC_nametable *nameT = &local_var->nameT[key];
+            if (nameT->num % NC_NAME_TABLE_CHUNK == 0)
+                nameT->list = (int*) NCI_Realloc(nameT->list,
+                              (size_t)(nameT->num+NC_NAME_TABLE_CHUNK) * sizeof(int));
+            nameT->list[nameT->num] = i;
+            nameT->num++;
+        }
+    }
+#endif
+
     return status;
 }
 
@@ -2263,13 +2322,17 @@ ncmpii_comp_vars(int          safe_mode,
  * header object, ncp, with root's header if any inconsistency is detected.
  * This function is called independently and should not contain any MPI
  * communication calls.
+ *
+ * Possible error codes returned:
+ * NC_ENOTNC3, NC_ENOTNC, NC_ESMALL, and all inconsistency errors
+ * NC_EMULTIDEFINE_XXX
  */
 int
 ncmpii_hdr_check_NC(bufferinfo *getbuf, /* header from root */
                     NC         *ncp)
 {
-    int rank, err, status=NC_NOERR;
-    schar magic[sizeof(ncmagic1)];
+    int err, status=NC_NOERR;
+    char magic[sizeof(ncmagic1)]; /* root's file format signature */
     MPI_Offset nrecs=0, chunksize=NC_DEFAULT_CHUNKSIZE;
     MPI_Aint pos_addr, base_addr;
     NC *root_ncp;
@@ -2277,12 +2340,9 @@ ncmpii_hdr_check_NC(bufferinfo *getbuf, /* header from root */
     assert(ncp != NULL);
     assert(getbuf != NULL);
 
-    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-
-    /* check header's magic */
+    /* check the file format signature in root's header */
     memset(magic, 0, sizeof(magic));
-    err = ncmpix_getn_schar_schar((const void **)(&getbuf->pos),
-                                  sizeof(magic), magic);
+    err = ncmpix_getn_text((const void **)(&getbuf->pos), sizeof(magic), magic);
     if (err != NC_NOERR) {
         /* Fatal error, as root's header is significant */
         if (ncp->safe_mode) fprintf(stderr,"Error: CDF magic number from root's header\n");
@@ -2293,58 +2353,77 @@ ncmpii_hdr_check_NC(bufferinfo *getbuf, /* header from root */
     /* check if the first 3 letters are "CDF" */
     if (memcmp(magic, ncmagic1, sizeof(ncmagic1)-1) != 0) {
         /* Fatal error, as root's header is significant */
-        if (ncp->safe_mode)
-            fprintf(stderr,"Error: root's header indicates not a CDF file\n");
-        DEBUG_RETURN_ERROR(NC_ENOTNC) /* should not continue */
+        /* check if is HDF5 file */
+        char signature[8], *hdf5_signature="\211HDF\r\n\032\n";
+        memcpy(signature, magic, 4);
+        ncmpix_getn_text((const void **)(&getbuf->pos), 4, signature+4);
+        if (memcmp(signature, hdf5_signature, 8) == 0) {
+            DEBUG_ASSIGN_ERROR(status, NC_ENOTNC3)
+            if (ncp->safe_mode)
+                fprintf(stderr,"Error: root's header indicates an HDF5 file\n");
+        }
+        else {
+            DEBUG_ASSIGN_ERROR(status, NC_ENOTNC)
+            if (ncp->safe_mode)
+                fprintf(stderr,"Error: root's header indicates not a CDF file\n");
+        }
+        return status; /* should not continue */
     }
 
     /* allocate a header object and fill it with root's header */
     root_ncp = ncmpii_new_NC(&chunksize);
 
-    /* consistency of magic numbers should have already been checked during
+    /* in safe_mode, consistency of magic numbers have already been checked in
      * ncmpi_create()
      */
     if (magic[sizeof(ncmagic1)-1] == 0x5) {
         fSet(root_ncp->flags, NC_64BIT_DATA);
+        root_ncp->format = 5;
+        getbuf->version = 5;
     }
     else if (magic[sizeof(ncmagic1)-1] == 0x2) {
         fSet(root_ncp->flags, NC_64BIT_OFFSET);
+        root_ncp->format = 2;
+        getbuf->version = 2;
     }
     else if (magic[sizeof(ncmagic1)-1] != 0x1) {
+        getbuf->version = 1;
+        root_ncp->format = 1;
         /* Fatal error, as root's header is significant */
         if (ncp->safe_mode)
             fprintf(stderr,"Error: root's header indicates not CDF 1/2/5 format\n");
         DEBUG_RETURN_ERROR(NC_ENOTNC) /* should not continue */
     }
 
-    /* check version number in last byte of magic */
-    int local_ver, root_ver;
-         if (ncp->flags & NC_64BIT_DATA)   local_ver = 0x5;
-    else if (ncp->flags & NC_64BIT_OFFSET) local_ver = 0x2;
-    else                                   local_ver = 0x1;
+    if (! ncp->safe_mode) {
+        /* check local's version number in last byte of magic against root's */
+        int root_ver = magic[sizeof(ncmagic1)-1];
 
-    root_ver = magic[sizeof(ncmagic1)-1];
-    if (local_ver != root_ver) {
-        if (ncp->safe_mode)
+        if (ncp->format != root_ver) {
+#ifdef PNETCDF_DEBUG
             printf("%s CDF file format (local=CDF-%d, root=CDF-%d)\n",
-                   WARN_STR, local_ver, root_ver);
+                   WARN_STR, ncp->format, root_ver);
+#endif
 
-        /* overwrite the local header object with root's */
-             if (local_ver == 0x5) fClr(ncp->flags, NC_64BIT_DATA);
-        else if (local_ver == 0x2) fClr(ncp->flags, NC_64BIT_OFFSET);
+            /* overwrite the local header object with root's */
+                 if (ncp->format == 5) fClr(ncp->flags, NC_64BIT_DATA);
+            else if (ncp->format == 2) fClr(ncp->flags, NC_64BIT_OFFSET);
 
-             if (root_ver  == 0x5) fSet(ncp->flags, NC_64BIT_DATA);
-        else if (root_ver  == 0x2) fSet(ncp->flags, NC_64BIT_OFFSET);
+                 if (root_ver == 5) fSet(ncp->flags, NC_64BIT_DATA);
+            else if (root_ver == 2) fSet(ncp->flags, NC_64BIT_OFFSET);
 
-        /* this inconsistency is not fatal */
-        DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_OMODE)
+            /* this inconsistency is not fatal */
+            DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_CMODE)
+        }
+        getbuf->version = root_ver;
+        ncp->format     = root_ver;
     }
-    getbuf->version = root_ver; /* getbuf's version has not been set before */
 
 #if SIZEOF_MPI_OFFSET < 8
-    if (root_ver > 1) {
+    if (getbuf->version > 1) {
         /* for NC_64BIT_DATA or NC_64BIT_OFFSET, MPI_Offset must be 8 bytes */
-        if (ncp->safe_mode) fprintf(stderr,"Error: cannot support CDF-2 and CDF-5 on this machine\n");
+        if (ncp->safe_mode)
+            fprintf(stderr,"Error: cannot support CDF-2 and CDF-5 on this machine\n");
         DEBUG_RETURN_ERROR(NC_ESMALL) /* should not continue */
     }
 #endif
@@ -2499,9 +2578,7 @@ int ncmpii_write_header(NC *ncp)
             }
         }
         else {
-            int put_size;
-            MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
-            ncp->nciop->put_size += put_size;
+            ncp->nciop->put_size += ncp->xsz;
         }
         NCI_Free(buf);
     }
diff --git a/src/lib/i_getput.m4 b/src/lib/i_getput.m4
index 9ae93f1..f6d6b6c 100644
--- a/src/lib/i_getput.m4
+++ b/src/lib/i_getput.m4
@@ -7,10 +7,10 @@ dnl
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: i_getput.m4 2320 2016-02-24 13:18:32Z wkliao $ */
+/* $Id: i_getput.m4 2588 2016-10-30 04:14:15Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -29,490 +29,6 @@ dnl
 #include "macro.h"
 
 
-define(`CollIndep',   `ifelse(`$1',`_all', `COLL_IO', `INDEP_IO')')dnl
-define(`ReadWrite',   `ifelse(`$1', `get', `READ_REQ', `WRITE_REQ')')dnl
-define(`BufConst',    `ifelse(`$1', `put', `const')')dnl
-
-dnl
-dnl VAR_FLEXIBLE
-dnl
-define(`VAR_FLEXIBLE',dnl
-`dnl
-/*----< ncmpi_i$1_var() >----------------------------------------------------*/
-int
-ncmpi_i$1_var(int                ncid,
-              int                varid,
-              BufConst($1) void *buf,
-              MPI_Offset         bufcount,
-              MPI_Datatype       buftype,
-              int               *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset *start, *count;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VAR,
-                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    GET_FULL_DIMENSIONS(start, count)
-
-    /* i$1_var is a special case of i$1_varm */
-    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                                 (void*)buf, bufcount, buftype, reqid,
-                                 ReadWrite($1), 0, 0);
-    NCI_Free(start);
-    return status;
-}
-')dnl
-
-VAR_FLEXIBLE(put)
-VAR_FLEXIBLE(get)
-
-dnl
-dnl VAR
-dnl
-define(`VAR',dnl
-`dnl
-/*----< ncmpi_i$1_var_$2() >-------------------------------------------------*/
-int
-ncmpi_i$1_var_$2(int              ncid,
-                 int              varid,
-                 BufConst($1) $3 *buf,
-                 int             *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset *start, *count;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, API_VAR,
-                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    GET_FULL_DIMENSIONS(start, count)
-
-    /* i$1_var is a special case of i$1_varm */
-    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                                 (void*)buf, -1, $4, reqid,
-                                 ReadWrite($1), 0, 0);
-    NCI_Free(start);
-    return status;
-}
-')dnl
-
-VAR(put, text,      char,               MPI_CHAR)
-VAR(put, schar,     schar,              MPI_SIGNED_CHAR)
-VAR(put, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR(put, short,     short,              MPI_SHORT)
-VAR(put, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR(put, int,       int,                MPI_INT)
-VAR(put, uint,      uint,               MPI_UNSIGNED)
-VAR(put, long,      long,               MPI_LONG)
-VAR(put, float,     float,              MPI_FLOAT)
-VAR(put, double,    double,             MPI_DOUBLE)
-VAR(put, longlong,  long long,          MPI_LONG_LONG_INT)
-VAR(put, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VAR(get, text,      char,               MPI_CHAR)
-VAR(get, schar,     schar,              MPI_SIGNED_CHAR)
-VAR(get, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR(get, short,     short,              MPI_SHORT)
-VAR(get, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR(get, int,       int,                MPI_INT)
-VAR(get, uint,      uint,               MPI_UNSIGNED)
-VAR(get, long,      long,               MPI_LONG)
-VAR(get, float,     float,              MPI_FLOAT)
-VAR(get, double,    double,             MPI_DOUBLE)
-VAR(get, longlong,  long long,          MPI_LONG_LONG_INT)
-VAR(get, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-
-dnl
-dnl VAR1_FLEXIBLE
-dnl
-define(`VAR1_FLEXIBLE',dnl
-`dnl
-/*----< ncmpi_i$1_var1() >---------------------------------------------------*/
-int
-ncmpi_i$1_var1(int                ncid,
-               int                varid,
-               const MPI_Offset  *start,
-               BufConst($1) void *buf,
-               MPI_Offset         bufcount,
-               MPI_Datatype       buftype,
-               int               *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset *count;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, NULL, bufcount, API_VAR1,
-                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    GET_ONE_COUNT(count)
-
-    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                                 (void*)buf, bufcount, buftype, reqid,
-                                 ReadWrite($1), 0, 0);
-    NCI_Free(count);
-    return status;
-}
-')dnl
-
-VAR1_FLEXIBLE(put)
-VAR1_FLEXIBLE(get)
-
-dnl
-dnl VAR1
-dnl
-define(`VAR1',dnl
-`dnl
-/*----< ncmpi_i$1_var1_$2() >------------------------------------------------*/
-int
-ncmpi_i$1_var1_$2(int               ncid,
-                  int               varid,
-                  const MPI_Offset  start[],
-                  BufConst($1) $3  *buf,
-                  int              *reqid)
-{
-    int         status;
-    NC         *ncp;
-    NC_var     *varp=NULL;
-    MPI_Offset *count;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, NULL, 0, API_VAR1,
-                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    GET_ONE_COUNT(count)
-
-    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                                 (void*)buf, -1, $4, reqid, ReadWrite($1), 0,
-                                 0);
-    NCI_Free(count);
-    return status;
-}
-')dnl
-
-VAR1(put, text,      char,               MPI_CHAR)
-VAR1(put, schar,     schar,              MPI_SIGNED_CHAR)
-VAR1(put, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR1(put, short,     short,              MPI_SHORT)
-VAR1(put, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR1(put, int,       int,                MPI_INT)
-VAR1(put, uint,      uint,               MPI_UNSIGNED)
-VAR1(put, long,      long,               MPI_LONG)
-VAR1(put, float,     float,              MPI_FLOAT)
-VAR1(put, double,    double,             MPI_DOUBLE)
-VAR1(put, longlong,  long long,          MPI_LONG_LONG_INT)
-VAR1(put, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VAR1(get, text,      char,               MPI_CHAR)
-VAR1(get, schar,     schar,              MPI_SIGNED_CHAR)
-VAR1(get, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VAR1(get, short,     short,              MPI_SHORT)
-VAR1(get, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VAR1(get, int,       int,                MPI_INT)
-VAR1(get, uint,      uint,               MPI_UNSIGNED)
-VAR1(get, long,      long,               MPI_LONG)
-VAR1(get, float,     float,              MPI_FLOAT)
-VAR1(get, double,    double,             MPI_DOUBLE)
-VAR1(get, longlong,  long long,          MPI_LONG_LONG_INT)
-VAR1(get, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-
-dnl
-dnl VARA_FLEXIBLE
-dnl
-define(`VARA_FLEXIBLE',dnl
-`dnl
-/*----< ncmpi_i$1_vara() >---------------------------------------------------*/
-int
-ncmpi_i$1_vara(int                ncid,
-               int                varid,
-               const MPI_Offset  *start,
-               const MPI_Offset  *count,
-               BufConst($1) void *buf,
-               MPI_Offset         bufcount,
-               MPI_Datatype       buftype,
-               int               *reqid)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARA,
-                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                               (void*)buf, bufcount, buftype, reqid,
-                               ReadWrite($1), 0, 0);
-}
-')dnl
-
-VARA_FLEXIBLE(put)
-VARA_FLEXIBLE(get)
-
-dnl
-dnl VARA
-dnl
-define(`VARA',dnl
-`dnl
-/*----< ncmpi_i$1_vara_$1() >------------------------------------------------*/
-int
-ncmpi_i$1_vara_$2(int               ncid,
-                  int               varid,
-                  const MPI_Offset  start[],
-                  const MPI_Offset  count[],
-                  BufConst($1) $3  *buf,
-                  int              *reqid)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARA,
-                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
-                               (void*)buf, -1, $4, reqid, ReadWrite($1), 0, 0);
-}
-')dnl
-
-VARA(put, text,      char,               MPI_CHAR)
-VARA(put, schar,     schar,              MPI_SIGNED_CHAR)
-VARA(put, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARA(put, short,     short,              MPI_SHORT)
-VARA(put, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARA(put, int,       int,                MPI_INT)
-VARA(put, uint,      uint,               MPI_UNSIGNED)
-VARA(put, long,      long,               MPI_LONG)
-VARA(put, float,     float,              MPI_FLOAT)
-VARA(put, double,    double,             MPI_DOUBLE)
-VARA(put, longlong,  long long,          MPI_LONG_LONG_INT)
-VARA(put, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARA(get, text,      char,               MPI_CHAR)
-VARA(get, schar,     schar,              MPI_SIGNED_CHAR)
-VARA(get, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARA(get, short,     short,              MPI_SHORT)
-VARA(get, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARA(get, int,       int,                MPI_INT)
-VARA(get, uint,      uint,               MPI_UNSIGNED)
-VARA(get, long,      long,               MPI_LONG)
-VARA(get, float,     float,              MPI_FLOAT)
-VARA(get, double,    double,             MPI_DOUBLE)
-VARA(get, longlong,  long long,          MPI_LONG_LONG_INT)
-VARA(get, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-
-dnl
-dnl VARS_FLEXIBLE
-dnl
-define(`VARS_FLEXIBLE',dnl
-`dnl
-/*----< ncmpi_i$1_vars() >---------------------------------------------------*/
-int
-ncmpi_i$1_vars(int                ncid,
-               int                varid,
-               const MPI_Offset   start[],
-               const MPI_Offset   count[],
-               const MPI_Offset   stride[],
-               BufConst($1) void *buf,
-               MPI_Offset         bufcount,
-               MPI_Datatype       buftype,
-               int               *reqid)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARS,
-                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, stride, NULL,
-                               (void*)buf, bufcount, buftype, reqid,
-                               ReadWrite($1), 0, 0);
-}
-')dnl
-
-VARS_FLEXIBLE(put)
-VARS_FLEXIBLE(get)
-
-dnl
-dnl VARS
-dnl
-define(`VARS',dnl
-`dnl
-/*----< ncmpi_i$1_vars_$2() >------------------------------------------------*/
-int
-ncmpi_i$1_vars_$2(int               ncid,
-                  int               varid,
-                  const MPI_Offset  start[],
-                  const MPI_Offset  count[],
-                  const MPI_Offset  stride[],
-                  BufConst($1) $3  *buf,
-                  int              *reqid)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARS,
-                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, stride, NULL,
-                               (void*)buf, -1, $4, reqid, ReadWrite($1), 0, 0);
-}
-')dnl
-
-VARS(put, text,      char,               MPI_CHAR)
-VARS(put, schar,     schar,              MPI_SIGNED_CHAR)
-VARS(put, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARS(put, short,     short,              MPI_SHORT)
-VARS(put, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARS(put, int,       int,                MPI_INT)
-VARS(put, uint,      uint,               MPI_UNSIGNED)
-VARS(put, long,      long,               MPI_LONG)
-VARS(put, float,     float,              MPI_FLOAT)
-VARS(put, double,    double,             MPI_DOUBLE)
-VARS(put, longlong,  long long,          MPI_LONG_LONG_INT)
-VARS(put, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARS(get, text,      char,               MPI_CHAR)
-VARS(get, schar,     schar,              MPI_SIGNED_CHAR)
-VARS(get, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARS(get, short,     short,              MPI_SHORT)
-VARS(get, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARS(get, int,       int,                MPI_INT)
-VARS(get, uint,      uint,               MPI_UNSIGNED)
-VARS(get, long,      long,               MPI_LONG)
-VARS(get, float,     float,              MPI_FLOAT)
-VARS(get, double,    double,             MPI_DOUBLE)
-VARS(get, longlong,  long long,          MPI_LONG_LONG_INT)
-VARS(get, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-
-/* buffer layers:
-
-        User Level              buf     (user defined buffer of MPI_Datatype)
-        MPI Datatype Level      cbuf    (contiguous buffer of ptype)
-        NetCDF XDR Level        xbuf    (XDR I/O buffer)
-*/
-
-static int
-pack_request(NC *ncp, NC_var *varp, NC_req *req,
-             const MPI_Offset start[], const MPI_Offset count[],
-             const MPI_Offset stride[]);
-
-dnl
-dnl VARM_FLEXIBLE
-dnl
-define(`VARM_FLEXIBLE',dnl
-`dnl
-/*----< ncmpi_i$1_varm() >---------------------------------------------------*/
-int
-ncmpi_i$1_varm(int                ncid,
-               int                varid,
-               const MPI_Offset   start[],
-               const MPI_Offset   count[],
-               const MPI_Offset   stride[],
-               const MPI_Offset   imap[],
-               BufConst($1) void *buf,
-               MPI_Offset         bufcount,
-               MPI_Datatype       buftype,
-               int               *reqid)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARM,
-                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, stride, imap,
-                               (void*)buf, bufcount, buftype, reqid,
-                               ReadWrite($1), 0, 0);
-}
-')dnl
-
-VARM_FLEXIBLE(put)
-VARM_FLEXIBLE(get)
-
-dnl
-dnl VARM
-dnl
-define(`VARM',dnl
-`dnl
-/*----< ncmpi_i$1_varm_$2() >------------------------------------------------*/
-int
-ncmpi_i$1_varm_$2(int               ncid,
-                  int               varid,
-                  const MPI_Offset  start[],
-                  const MPI_Offset  count[],
-                  const MPI_Offset  stride[],
-                  const MPI_Offset  imap[],
-                  BufConst($1) $3  *buf,
-                  int              *reqid)
-{
-    int     status;
-    NC     *ncp;
-    NC_var *varp=NULL;
-
-    if (reqid != NULL) *reqid = NC_REQ_NULL;
-    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARM,
-                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
-    if (status != NC_NOERR) return status;
-
-    return ncmpii_igetput_varm(ncp, varp, start, count, stride, imap,
-                               (void*)buf, -1, $4, reqid, ReadWrite($1), 0, 0);
-}
-')dnl
-
-VARM(put, text,      char,               MPI_CHAR)
-VARM(put, schar,     schar,              MPI_SIGNED_CHAR)
-VARM(put, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARM(put, short,     short,              MPI_SHORT)
-VARM(put, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARM(put, int,       int,                MPI_INT)
-VARM(put, uint,      uint,               MPI_UNSIGNED)
-VARM(put, long,      long,               MPI_LONG)
-VARM(put, float,     float,              MPI_FLOAT)
-VARM(put, double,    double,             MPI_DOUBLE)
-VARM(put, longlong,  long long,          MPI_LONG_LONG_INT)
-VARM(put, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARM(get, text,      char,               MPI_CHAR)
-VARM(get, schar,     schar,              MPI_SIGNED_CHAR)
-VARM(get, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARM(get, short,     short,              MPI_SHORT)
-VARM(get, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARM(get, int,       int,                MPI_INT)
-VARM(get, uint,      uint,               MPI_UNSIGNED)
-VARM(get, long,      long,               MPI_LONG)
-VARM(get, float,     float,              MPI_FLOAT)
-VARM(get, double,    double,             MPI_DOUBLE)
-VARM(get, longlong,  long long,          MPI_LONG_LONG_INT)
-VARM(get, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
 /*----< ncmpii_abuf_malloc() >------------------------------------------------*/
 /* allocate memory space from the attached buffer pool */
 static int
@@ -537,6 +53,75 @@ ncmpii_abuf_malloc(NC *ncp, MPI_Offset nbytes, void **buf, int *abuf_index)
     return NC_NOERR;
 }
 
+/*----< add_record_requests() >----------------------------------------------*/
+/* check if this is a record variable. if yes, add new requests for each
+ * record into the list. Hereinafter, treat each request as a non-record
+ * variable request
+ */
+static int
+add_record_requests(NC_var           *varp,
+                    NC_req           *reqs,
+                    const MPI_Offset *stride)
+{
+    int    i, j;
+    size_t dims_chunk = (size_t)varp->ndims * SIZEOF_MPI_OFFSET;
+    MPI_Offset record_bufcount, rec_bufsize;
+
+    record_bufcount = 1;
+    for (i=1; i<varp->ndims; i++)
+        record_bufcount *= reqs[0].count[i];
+    rec_bufsize = varp->xsz * record_bufcount;
+
+    /* append each record to the end of list */
+    for (i=1; i<reqs[0].count[0]; i++) {
+
+        reqs[i] = reqs[0]; /* inherit most attributes from reqs[0]
+                            * except below ones, including the ones need
+                            * malloc
+                            */
+
+        if (stride != NULL)
+            reqs[i].start = (MPI_Offset*) NCI_Malloc(dims_chunk*3);
+        else
+            reqs[i].start = (MPI_Offset*) NCI_Malloc(dims_chunk*2);
+
+        reqs[i].count = reqs[i].start + varp->ndims;
+
+        if (stride != NULL) {
+            reqs[i].stride    = reqs[i].count + varp->ndims;
+            reqs[i].start[0]  = reqs[0].start[0] + stride[0] * i;
+            reqs[i].stride[0] = reqs[0].stride[0];
+        } else {
+            reqs[i].stride   = NULL;
+            reqs[i].start[0] = reqs[0].start[0] + i;
+        }
+
+        reqs[i].count[0] = 1;
+        for (j=1; j<varp->ndims; j++) {
+            reqs[i].start[j]  = reqs[0].start[j];
+            reqs[i].count[j]  = reqs[0].count[j];
+            if (stride != NULL)
+                reqs[i].stride[j] = reqs[0].stride[j];
+        }
+
+        /* xbuf cannot be NULL    assert(reqs[0].xbuf != NULL); */
+
+        reqs[i].bnelems  = record_bufcount;
+        reqs[i].buf      = (char*)(reqs[i-1].buf)  + rec_bufsize;
+        reqs[i].xbuf     = (char*)(reqs[i-1].xbuf) + rec_bufsize;
+        reqs[i].num_recs = 0;  /* not the lead request */
+
+        /* reqs[i].bufcount and reqs[i].buftype will not be used in
+         * wait call, only the lead request's matters */
+    }
+
+    /* reset the lead request to one record at a time */
+    reqs[0].bnelems  = record_bufcount;
+    reqs[0].count[0] = 1;
+
+    return NC_NOERR;
+}
+
 /*----< ncmpii_igetput_varm() >-----------------------------------------------*/
 int
 ncmpii_igetput_varm(NC               *ncp,
@@ -557,6 +142,7 @@ ncmpii_igetput_varm(NC               *ncp,
     int err=NC_NOERR, status=NC_NOERR, warning=NC_NOERR;
     int i, abuf_index=-1, el_size, buftype_is_contig;
     int need_convert, need_swap, need_swap_back_buf=0;
+    size_t  dims_chunk;
     MPI_Offset bnelems=0, nbytes;
     MPI_Datatype ptype, imaptype=MPI_DATATYPE_NULL;
     NC_req *req;
@@ -595,15 +181,17 @@ ncmpii_igetput_varm(NC               *ncp,
         DEBUG_RETURN_ERROR(NC_EINSUFFBUF)
 
     /* check if type conversion and Endianness byte swap is needed */
-    need_convert = ncmpii_need_convert(varp->type, ptype);
+    need_convert = ncmpii_need_convert(ncp->format, varp->type, ptype);
     need_swap    = ncmpii_need_swap(varp->type, ptype);
 
-    /* check whether this is a true varm call, if yes, imaptype will be a
-     * newly created MPI derived data type, otherwise MPI_DATATYPE_NULL
-     */
-    err = ncmpii_create_imaptype(varp, count, imap, bnelems, el_size, ptype,
-                                 &imaptype);
-    if (err != NC_NOERR) return err;
+    if (imap != NULL) {
+        /* check whether this is a true varm call, if yes, imaptype will be a
+         * newly created MPI derived data type, otherwise MPI_DATATYPE_NULL
+         */
+        err = ncmpii_create_imaptype(varp, count, imap, bnelems, el_size,
+                                     ptype, &imaptype);
+        if (err != NC_NOERR) return err;
+    }
 
     if (rw_flag == WRITE_REQ) { /* pack request to xbuf */
         int position, abuf_allocated=0;
@@ -640,7 +228,7 @@ ncmpii_igetput_varm(NC               *ncp,
          */
 
         /* Step 1: pack buf into a contiguous buffer, lbuf, if buftype is
-         * not contiguous
+         * not contiguous, i.e. a noncontiguous MPI derived datatype
          */
         if (!buftype_is_contig) { /* buftype is not contiguous */
             if (bufcount != (int)bufcount) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
@@ -653,7 +241,7 @@ ncmpii_igetput_varm(NC               *ncp,
             }
             else lbuf = NCI_Malloc((size_t)outsize);
 
-            /* pack buf into lbuf using buftype */
+            /* pack buf into lbuf based on buftype */
             position = 0;
             MPI_Pack(buf, (int)bufcount, buftype, lbuf, (int)outsize,
                      &position, MPI_COMM_SELF);
@@ -675,24 +263,26 @@ ncmpii_igetput_varm(NC               *ncp,
             }
             else cbuf = NCI_Malloc((size_t)outsize);
 
-            /* pack lbuf to cbuf using imaptype */
+            /* pack lbuf to cbuf based on imaptype */
             position = 0;
             MPI_Pack(lbuf, 1, imaptype, cbuf, (int)outsize, &position,
                      MPI_COMM_SELF);
             MPI_Type_free(&imaptype);
+
+            /* lbuf is no longer needed */
+            if (lbuf != buf) NCI_Free(lbuf);
         }
         else /* not a true varm call: reuse lbuf */
             cbuf = lbuf;
 
-        /* lbuf is no longer needed */
-        if (lbuf != buf && lbuf != cbuf) NCI_Free(lbuf);
-
         /* Step 3: type-convert and byte-swap cbuf to xbuf, and xbuf will be
          * used in MPI write function to write to file
          */
 
         /* when user buf type != nc var type defined in file */
         if (need_convert) {
+            void *fillp; /* fill value in internal representation */
+
             if (use_abuf) { /* use attached buffer to allocate xbuf */
                 assert(abuf_allocated == 0);
                 status = ncmpii_abuf_malloc(ncp, nbytes, &xbuf, &abuf_index);
@@ -704,8 +294,15 @@ ncmpii_igetput_varm(NC               *ncp,
             }
             else xbuf = NCI_Malloc((size_t)nbytes);
 
+            /* find the fill value */
+            fillp = NCI_Malloc((size_t)varp->xsz);
+            ncmpii_inq_var_fill(varp, fillp);
+
             /* datatype conversion + byte-swap from cbuf to xbuf */
-            DATATYPE_PUT_CONVERT(varp->type, xbuf, cbuf, bnelems, ptype, status)
+            DATATYPE_PUT_CONVERT(ncp->format, varp->type, xbuf, cbuf, bnelems,
+                                 ptype, fillp, status)
+            NCI_Free(fillp);
+
             /* NC_ERANGE can be caused by a subset of buf that is out of range
              * of the external data type, it is not considered a fatal error.
              * The request must continue to finish.
@@ -748,7 +345,6 @@ ncmpii_igetput_varm(NC               *ncp,
         }
         /* cbuf is no longer needed */
         if (cbuf != buf && cbuf != xbuf) NCI_Free(cbuf);
-        if (!isSameGroup) ncp->numPutReqs++;
     }
     else { /* rw_flag == READ_REQ */
         /* Type conversion and byte swap for read are done at wait call, we
@@ -758,12 +354,44 @@ ncmpii_igetput_varm(NC               *ncp,
             xbuf = buf;  /* there is no buffered read (bget_var, etc.) */
         else
             xbuf = NCI_Malloc((size_t)nbytes);
-        if (!isSameGroup) ncp->numGetReqs++;
     }
 
-    /* allocate a new request object to store the write info */
-    req = (NC_req*) NCI_Malloc(sizeof(NC_req));
+    if (rw_flag == WRITE_REQ) {
+        /* allocate write/read request array */
+        if (ncp->numPutReqs % NC_REQUEST_CHUNK == 0)
+            ncp->put_list = (NC_req*) NCI_Realloc(ncp->put_list,
+                                      ((size_t)ncp->numPutReqs + NC_REQUEST_CHUNK) *
+                                      sizeof(NC_req));
+        req = ncp->put_list + ncp->numPutReqs;
+
+        /* the new request ID will be an even number (max of write ID + 2) */
+        req->id = 0;
+        if (ncp->numPutReqs > 0)
+            req->id = ncp->put_list[ncp->numPutReqs-1].id + 2;
+
+        ncp->numPutReqs++;
+    }
+    else {  /* READ_REQ */
+        /* allocate write/read request array */
+        if (ncp->numGetReqs % NC_REQUEST_CHUNK == 0)
+            ncp->get_list = (NC_req*) NCI_Realloc(ncp->get_list,
+                                      ((size_t)ncp->numGetReqs + NC_REQUEST_CHUNK) *
+                                      sizeof(NC_req));
+        req = ncp->get_list + ncp->numGetReqs;
+
+        /* the new request ID will be an odd number (max of read ID + 2) */
+        req->id = 1;
+        if (ncp->numGetReqs > 0)
+            req->id = ncp->get_list[ncp->numGetReqs-1].id + 2;
+
+        ncp->numGetReqs++;
+    }
+
+    /* if isSameGroup, then this request is from i_varn API */
+    if (isSameGroup && reqid != NULL)
+        req->id = *reqid;
 
+    req->varp               = varp;
     req->buf                = buf;
     req->xbuf               = xbuf;
     req->bnelems            = bnelems;
@@ -772,10 +400,14 @@ ncmpii_igetput_varm(NC               *ncp,
     req->buftype_is_contig  = buftype_is_contig;
     req->need_swap_back_buf = need_swap_back_buf;
     req->imaptype           = imaptype;
-    req->rw_flag            = rw_flag;
     req->abuf_index         = abuf_index;
     req->tmpBuf             = NULL;
     req->userBuf            = NULL;
+    req->status             = NULL;
+    req->num_recs           = 1;   /* For record variable, this will be set to
+                                    * the number of records requested. For
+                                    * fixed-size variable, this will be 1.
+                                    */
 
     /* only when read and buftype is not contiguous, we duplicate buftype for
      * later in the wait call to unpack buffer based on buftype
@@ -785,54 +417,8 @@ ncmpii_igetput_varm(NC               *ncp,
     else
         req->buftype = MPI_DATATYPE_NULL;
 
-    pack_request(ncp, varp, req, start, count, stride);
-
-    /* add the new request to the internal request array (or linked list) */
-    if (ncp->head == NULL) {
-        req->id   = 0;
-        ncp->head = req;
-        ncp->tail = ncp->head;
-    }
-    else { /* add to the tail */
-        if (!isSameGroup)
-            req->id = ncp->tail->id + 1;
-        else if (reqid != NULL)
-            req->id = *reqid;
-        ncp->tail->next = req;
-        ncp->tail = req;
-    }
-    for (i=0; i<req->num_subreqs; i++)
-        req->subreqs[i].id = req->id;
-
-    /* return the request ID */
-    if (reqid != NULL) *reqid = req->id;
-
-    return ((warning != NC_NOERR) ? warning : status);
-}
-
-/*----< pack_request() >------------------------------------------------------*/
-/* if this request is for a record variable, then we break this request into
- * sub-requests, each for a record
- */
-static int
-pack_request(NC               *ncp,
-             NC_var           *varp,
-             NC_req           *req,
-             const MPI_Offset  start[],
-             const MPI_Offset  count[],
-             const MPI_Offset  stride[])
-{
-    int     i, j;
-    size_t  dims_chunk;
-    NC_req *subreqs;
-
-    dims_chunk       = (size_t)varp->ndims * SIZEOF_MPI_OFFSET;
-
-    req->varp        = varp;
-    req->next        = NULL;
-    req->subreqs     = NULL;
-    req->num_subreqs = 0;
-
+    /* allocate start/count/stride arrays */
+    dims_chunk = (size_t)varp->ndims * SIZEOF_MPI_OFFSET;
     if (stride != NULL)
         req->start = (MPI_Offset*) NCI_Malloc(dims_chunk*3);
     else
@@ -845,6 +431,7 @@ pack_request(NC               *ncp,
     else
         req->stride = NULL;
 
+    /* set the values for start/count/stride */
     for (i=0; i<varp->ndims; i++) {
         req->start[i] = start[i];
         req->count[i] = count[i];
@@ -852,91 +439,76 @@ pack_request(NC               *ncp,
             req->stride[i] = stride[i];
     }
 
-#ifdef _DISALLOW_POST_NONBLOCKING_API_IN_DEFINE_MODE
-    /* move the offset calculation to wait time (ncmpii_wait_getput),
-     * such that posting a nonblocking request can be done in define
-     * mode
+    /* if this is a record variable and number of requesting records is > 1,
+     * we split the request, one for each record
      */
+    if (IS_RECVAR(varp) && req->count[0] > 1) {
+        req->num_recs = req->count[0];
 
-    /* get the starting file offset for this request */
-    ncmpii_get_offset(ncp, varp, start, NULL, NULL, req->rw_flag,
-                      &req->offset_start);
-
-    /* get the ending file offset for this request */
-    ncmpii_get_offset(ncp, varp, start, count, stride, req->rw_flag,
-                      &req->offset_end);
-    req->offset_end += varp->xsz - 1;
-#endif
+        add_record_requests(varp, req, stride);
+        /* req->count[0] has been changed to 1 */
 
-    /* check if this is a record variable. if yes, split the request into
-     * subrequests, one subrequest for a record access. Hereinafter,
-     * treat each request as a non-record variable request
-     */
-
-    /* check if this access is within one record, if yes, no need to create
-       subrequests */
-    if (IS_RECVAR(varp) && req->count[0] > 1) {
-        MPI_Offset rec_bufcount = 1;
-        for (i=1; i<varp->ndims; i++)
-            rec_bufcount *= req->count[i];
+        if (rw_flag == WRITE_REQ) ncp->numPutReqs += req->num_recs - 1;
+        else                      ncp->numGetReqs += req->num_recs - 1;
+    }
 
-        subreqs = (NC_req*) NCI_Malloc((size_t)req->count[0]*sizeof(NC_req));
-        for (i=0; i<req->count[0]; i++) {
-            MPI_Offset span;
-            subreqs[i] = *req; /* inherit most attributes from req */
+    /* return the request ID */
+    if (reqid != NULL) *reqid = req->id;
 
-            /* each sub-request contains <= one record size */
-            if (stride != NULL)
-                subreqs[i].start = (MPI_Offset*) NCI_Malloc(dims_chunk*3);
-            else
-                subreqs[i].start = (MPI_Offset*) NCI_Malloc(dims_chunk*2);
-
-            subreqs[i].count = subreqs[i].start + varp->ndims;
-
-            if (stride != NULL) {
-                subreqs[i].stride = subreqs[i].count + varp->ndims;
-                subreqs[i].start[0] = req->start[0] + stride[0] * i;
-                subreqs[i].stride[0] = req->stride[0];
-            } else {
-                subreqs[i].stride = NULL;
-                subreqs[i].start[0] = req->start[0] + i;
-            }
+    return ((warning != NC_NOERR) ? warning : status);
+}
 
-            subreqs[i].count[0] = 1;
-            subreqs[i].bnelems = 1;
-            for (j=1; j<varp->ndims; j++) {
-                subreqs[i].start[j]  = req->start[j];
-                subreqs[i].count[j]  = req->count[j];
-                subreqs[i].bnelems  *= subreqs[i].count[j];
-                if (stride != NULL)
-                    subreqs[i].stride[j] = req->stride[j];
-            }
+include(`foreach.m4')dnl
+include(`utils.m4')dnl
+dnl
+define(`APINAME',`ifelse(`$3',`',`ncmpi_i$1_var$2',`ncmpi_i$1_var$2_$3')')dnl
+dnl
+dnl IGETPUT_API(get/put, kind, itype)
+dnl
+define(`IGETPUT_API',dnl
+`dnl
+/*----< APINAME($1,$2,$3)() >------------------------------------------------*/
+int
+APINAME($1,$2,$3)(int ncid, int varid, ArgKind($2) BufArgs($1,$3), int *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    ifelse(`$2', `',  `MPI_Offset *start, *count;',
+           `$2', `1', `MPI_Offset *count;')
 
-#ifdef _DISALLOW_POST_NONBLOCKING_API_IN_DEFINE_MODE
-            /* move the offset calculation to wait time (ncmpii_wait_getput),
-             * such that posting a nonblocking request can be done in define
-             * mode
-             */
-            ncmpii_get_offset(ncp, varp, subreqs[i].start, NULL, NULL,
-                              subreqs[i].rw_flag, &subreqs[i].offset_start);
-            ncmpii_get_offset(ncp, varp, subreqs[i].start,
-                              subreqs[i].count, subreqs[i].stride,
-                              subreqs[i].rw_flag, &subreqs[i].offset_end);
-            subreqs[i].offset_end += varp->xsz - 1;
-#endif
-            span                = i*rec_bufcount*varp->xsz;
-            subreqs[i].buf      = (char*)(req->buf)  + span;
-            /* xbuf cannot be NULL    assert(req->xbuf != NULL); */
-            subreqs[i].xbuf     = (char*)(req->xbuf) + span;
-            subreqs[i].bufcount = rec_bufcount;
-        }
-        req->num_subreqs = (int)req->count[0];
-        req->subreqs     = subreqs;
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, ArgStartCount($2),
+                                 ifelse(`$3', `', `bufcount', `0'),
+                                 ifelse(`$3', `', `buftype',  `ITYPE2MPI($3)'),
+                                 API_KIND($2), ifelse(`$2', `', `1', `0'),
+                                 0, ReadWrite($1),
+                                 NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
 
-        if (req->count[0] != (int)req->count[0])
-            DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
-    }
+    ifelse(`$2', `',  `GET_FULL_DIMENSIONS(start, count)',
+           `$2', `1', `GET_ONE_COUNT(count)')
 
-    return NC_NOERR;
+    /* APINAME($1,$2,$3) is a special case of APINAME($1,m,$3) */
+    status = ncmpii_igetput_varm(ncp, varp, start, count, ArgStrideMap($2),
+                                 (void*)buf,
+                                 ifelse(`$3', `', `bufcount, buftype',
+                                                  `-1, ITYPE2MPI($3)'),
+                                 reqid, ReadWrite($1), 0, 0);
+    ifelse(`$2', `', `NCI_Free(start);', `$2', `1', `NCI_Free(count);')
+    return status;
 }
-
+')dnl
+dnl
+/*---- PnetCDF flexible APIs ------------------------------------------------*/
+foreach(`kind', (, 1, a, s, m),
+        `foreach(`putget', (put, get),
+                 `IGETPUT_API(putget,kind,)'
+)')
+
+/*---- PnetCDF high-level APIs ----------------------------------------------*/
+foreach(`kind', (, 1, a, s, m),
+        `foreach(`putget', (put, get),
+                 `foreach(`itype', (ITYPE_LIST),
+                          `IGETPUT_API(putget,kind,itype)'
+)')')
diff --git a/src/lib/i_varn.m4 b/src/lib/i_varn.m4
index 35248e9..bd5b75e 100644
--- a/src/lib/i_varn.m4
+++ b/src/lib/i_varn.m4
@@ -7,10 +7,10 @@ dnl
  *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: i_varn.m4 2321 2016-02-24 21:50:14Z wkliao $ */
+/* $Id: i_varn.m4 2559 2016-10-16 20:47:09Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -27,6 +27,9 @@ dnl
 #include "ncmpidtype.h"
 #include "macro.h"
 
+include(`foreach.m4')
+include(`utils.m4')
+
 /* ncmpi_iget/iput_varn_<type>_<mode> API:
  *    type:   data type of I/O buffer, buf
  *    mode:   indpendent (<nond>) or collective (_all)
@@ -61,7 +64,6 @@ ncmpii_igetput_varn(NC               *ncp,
 
 dnl
 define(`IsBput',    `ifelse(`$1',`bput', `1', `0')')dnl
-define(`ReadWrite', `ifelse(`$1',`iget', `READ_REQ', `WRITE_REQ')')dnl
 define(`BufConst',  `ifelse(`$1',`iget', , `const')')dnl
 dnl
 dnl VARN_FLEXIBLE()
@@ -89,8 +91,9 @@ ncmpi_$1_varn(int                 ncid,
     /* check for zero-size request */
     if (num == 0 || bufcount == 0) return NC_NOERR;
 
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARN,
-                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, buftype,
+                                 API_VARN, 1,
+                                 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
     if (status != NC_NOERR) return status;
 
     return ncmpii_igetput_varn(ncp, varp, num, starts, counts, (void*)buf,
@@ -128,8 +131,9 @@ ncmpi_$1_varn_$2(int                ncid,
     /* check for zero request */
     if (num == 0) return NC_NOERR;
 
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, API_VARN,
-                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, ITYPE2MPI($2),
+                                 API_VARN, 0,
+                                 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
     if (status != NC_NOERR) return status;
 
     /* set bufcount to -1 indicating non-flexible API */
@@ -137,46 +141,11 @@ ncmpi_$1_varn_$2(int                ncid,
                                -1, $4, reqid, ReadWrite($1), IsBput($1));
 }
 ')dnl
-
-VARN(iput, text,      char,               MPI_CHAR)
-VARN(iput, schar,     schar,              MPI_SIGNED_CHAR)
-VARN(iput, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARN(iput, short,     short,              MPI_SHORT)
-VARN(iput, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARN(iput, int,       int,                MPI_INT)
-VARN(iput, uint,      uint,               MPI_UNSIGNED)
-VARN(iput, long,      long,               MPI_LONG)
-VARN(iput, float,     float,              MPI_FLOAT)
-VARN(iput, double,    double,             MPI_DOUBLE)
-VARN(iput, longlong,  long long,          MPI_LONG_LONG_INT)
-VARN(iput, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARN(iget, text,      char,               MPI_CHAR)
-VARN(iget, schar,     schar,              MPI_SIGNED_CHAR)
-VARN(iget, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARN(iget, short,     short,              MPI_SHORT)
-VARN(iget, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARN(iget, int,       int,                MPI_INT)
-VARN(iget, uint,      uint,               MPI_UNSIGNED)
-VARN(iget, long,      long,               MPI_LONG)
-VARN(iget, float,     float,              MPI_FLOAT)
-VARN(iget, double,    double,             MPI_DOUBLE)
-VARN(iget, longlong,  long long,          MPI_LONG_LONG_INT)
-VARN(iget, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARN(bput, text,      char,               MPI_CHAR)
-VARN(bput, schar,     schar,              MPI_SIGNED_CHAR)
-VARN(bput, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARN(bput, short,     short,              MPI_SHORT)
-VARN(bput, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARN(bput, int,       int,                MPI_INT)
-VARN(bput, uint,      uint,               MPI_UNSIGNED)
-VARN(bput, long,      long,               MPI_LONG)
-VARN(bput, float,     float,              MPI_FLOAT)
-VARN(bput, double,    double,             MPI_DOUBLE)
-VARN(bput, longlong,  long long,          MPI_LONG_LONG_INT)
-VARN(bput, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
+dnl
+foreach(`putget', (iput, iget, bput),
+        `foreach(`itype', (ITYPE_LIST),
+                 `VARN(putget,itype,FUNC2ITYPE(itype),ITYPE2MPI(itype))
+')')
 
 /*----< ncmpii_igetput_varn() >-----------------------------------------------*/
 static int
@@ -201,10 +170,19 @@ ncmpii_igetput_varn(NC               *ncp,
     if (use_abuf && ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
 
     /* it is illegal for starts to be NULL */
-    if (starts == NULL) DEBUG_RETURN_ERROR(NC_ENULLSTART)
+    if (starts == NULL)
+        DEBUG_RETURN_ERROR(NC_ENULLSTART)
+    else { /* it is illegal for any starts[i] to be NULL */
+        for (i=0; i<num; i++) {
+            if (starts[i] == NULL)
+                DEBUG_RETURN_ERROR(NC_ENULLSTART)
+        }
+    }
 
     if (counts != NULL) {
         for (j=0; j<num; j++) {
+            if (counts[j] == NULL)
+                DEBUG_RETURN_ERROR(NC_ENULLCOUNT)
             for (i=0; i<varp->ndims; i++) {
                 if (counts[j][i] < 0) /* no negative counts[][] */
                     DEBUG_RETURN_ERROR(NC_ENEGATIVECNT)
@@ -272,8 +250,10 @@ ncmpii_igetput_varn(NC               *ncp,
             for (j=0; j<varp->ndims; j++)
                 _counts[i][j] = 1;
     }
-    else
+    else {
         _counts = (MPI_Offset**) counts;
+    }
+    /* from this point forward, _counts != NULL */
 
     /* break buf into num pieces */
     reqid = NC_REQ_NULL;
@@ -302,26 +282,35 @@ ncmpii_igetput_varn(NC               *ncp,
         bufp += buflen * el_size;
     }
 
-    /* add callback if buftype is noncontiguous */
     if (free_cbuf) { /* cbuf != buf, cbuf is temp allocated */
         if (rw_flag == READ_REQ) {
-            /* tell wait() to unpack cbuf to buf and free cbuf */
-            status = ncmpii_set_iget_callback(ncp, reqid, cbuf, buf,
-                                              (int)bufcount, buftype);
+            /* Set the last lead request object to let wait() unpack cbuf to
+             * buf and free cbuf */
+            for (i=ncp->numGetReqs-1; i>=0; i--)
+                if (ncp->get_list[i].num_recs > 0)
+                    break;
+            ncp->get_list[i].tmpBuf   = cbuf;
+            ncp->get_list[i].userBuf  = buf;
+            ncp->get_list[i].bufcount = (int)bufcount;
+            MPI_Type_dup(buftype, &ncp->get_list[i].buftype);
         }
         else { /* WRITE_REQ */
             if (use_abuf)
                 /* cbuf has been copied to the attached buffer, so it is safe
                  * to free cbuf now */
                 NCI_Free(cbuf);
-            else
-                /* tell wait() to free cbuf once done */
-                status = ncmpii_set_iput_callback(ncp, reqid, cbuf);
+            else {
+                for (i=ncp->numPutReqs-1; i>=0; i--)
+                    if (ncp->put_list[i].num_recs > 0)
+                        break;
+                    /* Set the last request object to let wait() to free cbuf */
+                    ncp->put_list[i].tmpBuf = cbuf;
+            }
         }
     }
 
 err_check:
-    if (_counts != NULL && _counts != counts) {
+    if (_counts != counts) {
         NCI_Free(_counts[0]);
         NCI_Free(_counts);
     }
diff --git a/src/lib/m_getput_varx.m4 b/src/lib/m_getput_varx.m4
index 04ef060..ebb2f89 100644
--- a/src/lib/m_getput_varx.m4
+++ b/src/lib/m_getput_varx.m4
@@ -7,10 +7,10 @@ dnl
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: m_getput_varx.m4 2320 2016-02-24 13:18:32Z wkliao $ */
+/* $Id: m_getput_varx.m4 2475 2016-09-05 23:15:29Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
diff --git a/src/lib/macro.h b/src/lib/macro.h
index 5dedec8..cec30b6 100644
--- a/src/lib/macro.h
+++ b/src/lib/macro.h
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: macro.h 2196 2015-11-27 22:31:05Z wkliao $ */
+/* $Id: macro.h 2590 2016-10-31 21:37:02Z wkliao $ */
 
 #ifndef _H_MACRO
 #define _H_MACRO
@@ -37,28 +37,40 @@ void  NCI_Free_fn(void *ptr, int lineno, const char *func, const char *fname);
     }                                                                         \
 }
 
-#ifdef PNC_DEBUG
+#ifdef PNETCDF_DEBUG
 #define DEBUG_RETURN_ERROR(err) {                                       \
-    int _rank;                                                          \
-    char *env_str = getenv("PNETCDF_VERBOSE_DEBUG_MODE");               \
-    MPI_Comm_rank(MPI_COMM_WORLD, &_rank);                              \
-    if (env_str != NULL && *env_str != '0')                             \
+    char *_env_str = getenv("PNETCDF_VERBOSE_DEBUG_MODE");              \
+    if (_env_str != NULL && *_env_str != '0') {                         \
+        int _rank;                                                      \
+        MPI_Comm_rank(MPI_COMM_WORLD, &_rank);                          \
         fprintf(stderr, "Rank %d: %s error at line %d of %s in %s\n",   \
-        _rank,ncmpii_err_code_name(err),__LINE__,__func__,__FILE__);    \
+        _rank,ncmpi_strerrno(err),__LINE__,__func__,__FILE__);          \
+    }                                                                   \
     return err;                                                         \
 }
 #define DEBUG_ASSIGN_ERROR(status, err) {                               \
-    int _rank;                                                          \
-    char *env_str = getenv("PNETCDF_VERBOSE_DEBUG_MODE");               \
-    MPI_Comm_rank(MPI_COMM_WORLD, &_rank);                              \
-    if (env_str != NULL && *env_str != '0')                             \
+    char *_env_str = getenv("PNETCDF_VERBOSE_DEBUG_MODE");              \
+    if (_env_str != NULL && *_env_str != '0') {                         \
+        int _rank;                                                      \
+        MPI_Comm_rank(MPI_COMM_WORLD, &_rank);                          \
         fprintf(stderr, "Rank %d: %s error at line %d of %s in %s\n",   \
-        _rank,ncmpii_err_code_name(err),__LINE__,__func__,__FILE__);    \
+        _rank,ncmpi_strerrno(err),__LINE__,__func__,__FILE__);          \
+    }                                                                   \
     status = err;                                                       \
 }
+#define DEBUG_TRACE_ERROR {                                             \
+    char *_env_str = getenv("PNETCDF_VERBOSE_DEBUG_MODE");              \
+    if (_env_str != NULL && *_env_str != '0') {                         \
+        int _rank;                                                      \
+        MPI_Comm_rank(MPI_COMM_WORLD, &_rank);                          \
+        fprintf(stderr, "Rank %d: %s error at line %d of %s in %s\n",   \
+        _rank,ncmpi_strerrno(err),__LINE__,__func__,__FILE__);          \
+    }                                                                   \
+}
 #else
 #define DEBUG_RETURN_ERROR(err) return err;
 #define DEBUG_ASSIGN_ERROR(status, err) status = err;
+#define DEBUG_TRACE_ERROR
 #endif
 
 #define GET_ONE_COUNT(count) {                                                \
@@ -105,39 +117,42 @@ void  NCI_Free_fn(void *ptr, int lineno, const char *func, const char *fname);
 }
 #endif
 
-#define DATATYPE_GET_CONVERT(vartype, inbuf, outbuf, cnelems, memtype, err) { \
-    /* vartype is the variable's data type defined in the nc file             \
-     * memtype is the I/O buffers data type (MPI_Datatype)  */                \
-    switch(vartype) {                                                         \
+#define DATATYPE_GET_CONVERT(cdf_ver,xtype,xbuf,ibuf,bnelems,itype,err) {     \
+    /* xtype is the NC variable's external data type stored in the nc file    \
+     * itype (internal type) is the user I/O buffer data type (MPI_Datatype)  \
+     * xbuf is the buffer containing the data read from the nc file in the    \
+     * external representation, to be converted to internal representation r  \
+     * into user buffer, ibuf */                                              \
+    switch(xtype) {                                                           \
         case NC_BYTE:                                                         \
-            err = ncmpii_x_getn_schar(inbuf, outbuf, cnelems, memtype);       \
+            err = ncmpii_x_getn_NC_BYTE(cdf_ver,xbuf,ibuf,bnelems,itype);     \
             break;                                                            \
         case NC_UBYTE:                                                        \
-            err = ncmpii_x_getn_uchar(inbuf, outbuf, cnelems, memtype);       \
+            err = ncmpii_x_getn_NC_UBYTE(xbuf,ibuf,bnelems,itype);            \
             break;                                                            \
         case NC_SHORT:                                                        \
-            err = ncmpii_x_getn_short(inbuf, outbuf, cnelems, memtype);       \
+            err = ncmpii_x_getn_NC_SHORT(xbuf,ibuf,bnelems,itype);            \
             break;                                                            \
         case NC_USHORT:                                                       \
-            err = ncmpii_x_getn_ushort(inbuf, outbuf, cnelems, memtype);      \
+            err = ncmpii_x_getn_NC_USHORT(xbuf,ibuf,bnelems,itype);           \
             break;                                                            \
         case NC_INT:                                                          \
-            err = ncmpii_x_getn_int(inbuf, outbuf, cnelems, memtype);         \
+            err = ncmpii_x_getn_NC_INT(xbuf,ibuf,bnelems,itype);              \
             break;                                                            \
         case NC_UINT:                                                         \
-            err = ncmpii_x_getn_uint(inbuf, outbuf, cnelems, memtype);        \
+            err = ncmpii_x_getn_NC_UINT(xbuf,ibuf,bnelems,itype);             \
             break;                                                            \
         case NC_FLOAT:                                                        \
-            err = ncmpii_x_getn_float(inbuf, outbuf, cnelems, memtype);       \
+            err = ncmpii_x_getn_NC_FLOAT(xbuf,ibuf,bnelems,itype);            \
             break;                                                            \
         case NC_DOUBLE:                                                       \
-            err = ncmpii_x_getn_double(inbuf, outbuf, cnelems, memtype);      \
+            err = ncmpii_x_getn_NC_DOUBLE(xbuf,ibuf,bnelems,itype);           \
             break;                                                            \
         case NC_INT64:                                                        \
-            err = ncmpii_x_getn_int64(inbuf, outbuf, cnelems, memtype);       \
+            err = ncmpii_x_getn_NC_INT64(xbuf,ibuf,bnelems,itype);            \
             break;                                                            \
         case NC_UINT64:                                                       \
-            err = ncmpii_x_getn_uint64(inbuf, outbuf, cnelems, memtype);      \
+            err = ncmpii_x_getn_NC_UINT64(xbuf,ibuf,bnelems,itype);           \
             break;                                                            \
         default:                                                              \
             err = NC_EBADTYPE;                                                \
@@ -145,39 +160,43 @@ void  NCI_Free_fn(void *ptr, int lineno, const char *func, const char *fname);
     }                                                                         \
 }
 
-#define DATATYPE_PUT_CONVERT(vartype, outbuf, inbuf, cnelems, memtype, err) { \
-    /* vartype is the variable's data type defined in the nc file             \
-     * memtype is the I/O buffers data type (MPI_Datatype)  */                \
-    switch(vartype) {                                                         \
+#define DATATYPE_PUT_CONVERT(cdf_ver,xtype,xbuf,ibuf,cnelems,itype,fillp,err) {\
+    /* xtype is the NC variable's external data type stored in the nc file    \
+     * itype (internal type)is the user I/O buffer data type (MPI_Datatype)   \
+     * ibuf is user buffer containing the data in internal format of itype,   \
+     * they meed to be converted to external format to external buffer, xbuf, \
+     * so xbuf can be used to write to the nc file through the call to        \
+     * MPI_FIle_write call */                                                 \
+    switch(xtype) {                                                           \
         case NC_BYTE:                                                         \
-            err = ncmpii_x_putn_schar(outbuf, inbuf, cnelems, memtype);       \
+            err = ncmpii_x_putn_NC_BYTE(cdf_ver,xbuf,ibuf,cnelems,itype,fillp);\
             break;                                                            \
         case NC_UBYTE:                                                        \
-            err = ncmpii_x_putn_uchar(outbuf, inbuf, cnelems, memtype);       \
+            err = ncmpii_x_putn_NC_UBYTE(xbuf,ibuf,cnelems,itype,fillp);      \
             break;                                                            \
         case NC_SHORT:                                                        \
-            err = ncmpii_x_putn_short(outbuf, inbuf, cnelems, memtype);       \
+            err = ncmpii_x_putn_NC_SHORT(xbuf,ibuf,cnelems,itype,fillp);      \
             break;                                                            \
         case NC_USHORT:                                                       \
-            err = ncmpii_x_putn_ushort(outbuf, inbuf, cnelems, memtype);      \
+            err = ncmpii_x_putn_NC_USHORT(xbuf,ibuf,cnelems,itype,fillp);     \
             break;                                                            \
         case NC_INT:                                                          \
-            err = ncmpii_x_putn_int(outbuf, inbuf, cnelems, memtype);         \
+            err = ncmpii_x_putn_NC_INT(xbuf,ibuf,cnelems,itype,fillp);        \
             break;                                                            \
         case NC_UINT:                                                         \
-            err = ncmpii_x_putn_uint(outbuf, inbuf, cnelems, memtype);        \
+            err = ncmpii_x_putn_NC_UINT(xbuf,ibuf,cnelems,itype,fillp);       \
             break;                                                            \
         case NC_FLOAT:                                                        \
-            err = ncmpii_x_putn_float(outbuf, inbuf, cnelems, memtype);       \
+            err = ncmpii_x_putn_NC_FLOAT(xbuf,ibuf,cnelems,itype,fillp);      \
             break;                                                            \
         case NC_DOUBLE:                                                       \
-            err = ncmpii_x_putn_double(outbuf, inbuf, cnelems, memtype);      \
+            err = ncmpii_x_putn_NC_DOUBLE(xbuf,ibuf,cnelems,itype,fillp);     \
             break;                                                            \
         case NC_INT64:                                                        \
-            err = ncmpii_x_putn_int64(outbuf, inbuf, cnelems, memtype);       \
+            err = ncmpii_x_putn_NC_INT64(xbuf,ibuf,cnelems,itype,fillp);      \
             break;                                                            \
         case NC_UINT64:                                                       \
-            err = ncmpii_x_putn_uint64(outbuf, inbuf, cnelems, memtype);      \
+            err = ncmpii_x_putn_NC_UINT64(xbuf,ibuf,cnelems,itype,fillp);     \
             break;                                                            \
         default:                                                              \
             err = NC_EBADTYPE;                                                \
diff --git a/src/lib/malloc.c b/src/lib/malloc.c
index 0ec953f..68b2809 100644
--- a/src/lib/malloc.c
+++ b/src/lib/malloc.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: malloc.c 2244 2015-12-19 22:41:28Z wkliao $ */
+/* $Id: malloc.c 2590 2016-10-31 21:37:02Z wkliao $ */
 
 /* These are routines for allocating and deallocating memory.
    They should be called as NCI_Malloc(size) and
@@ -12,7 +12,7 @@
  */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdlib.h>
@@ -187,7 +187,7 @@ void *NCI_Malloc_fn(size_t      size,
                     const char *func,
                     const char *filename)
 {
-#ifdef NC_DEBUG
+#ifdef _DEBUG
     if (size == 0)
         fprintf(stderr, "Attempt to malloc zero-size in file %s, line %d\n", filename, lineno);
 #endif
@@ -195,7 +195,9 @@ void *NCI_Malloc_fn(size_t      size,
     void *buf = malloc(size);
     if (!buf) {
 	fprintf(stderr, "malloc(%zd) failed in file %s, line %d\n", size, filename, lineno);
+#ifdef PNETCDF_DEBUG
 	MPI_Abort(MPI_COMM_WORLD, 1);
+#endif
     }
 #ifdef PNC_MALLOC_TRACE
     ncmpii_add_mem_entry(buf, size, lineno, func, filename);
@@ -211,7 +213,7 @@ void *NCI_Calloc_fn(size_t      nelem,
                     const char *func,
                     const char *filename)
 {
-#ifdef NC_DEBUG
+#ifdef _DEBUG
     if (nelem == 0 || elsize == 0)
         fprintf(stderr, "Attempt to calloc zero-size in file %s, line %d\n", filename, lineno);
 #endif
@@ -219,7 +221,9 @@ void *NCI_Calloc_fn(size_t      nelem,
     void *buf =calloc(nelem, elsize);
     if (!buf) {
 	fprintf(stderr, "calloc(%zd, %zd) failed in file %s, line %d\n", nelem, elsize, filename, lineno);
+#ifdef PNETCDF_DEBUG
 	MPI_Abort(MPI_COMM_WORLD, 1);
+#endif
     }
 #ifdef PNC_MALLOC_TRACE
     ncmpii_add_mem_entry(buf, nelem * elsize, lineno, func, filename);
@@ -235,7 +239,7 @@ void *NCI_Realloc_fn(void       *ptr,
                      const char *func,
                      const char *filename)
 {
-#ifdef NC_DEBUG
+#ifdef _DEBUG
     if (size == 0)
         fprintf(stderr, "Attempt to realloc zero-size in file %s, line %d\n", filename, lineno);
 #endif
@@ -246,7 +250,9 @@ void *NCI_Realloc_fn(void       *ptr,
     void *buf = (void *) realloc(ptr, size);
     if (!buf) {
 	fprintf(stderr, "realloc failed in file %s, line %d\n", filename, lineno);
+#ifdef PNETCDF_DEBUG
 	MPI_Abort(MPI_COMM_WORLD, 1);
+#endif
     }
 #ifdef PNC_MALLOC_TRACE
     ncmpii_add_mem_entry(buf, size, lineno, func, filename);
@@ -261,7 +267,7 @@ void NCI_Free_fn(void       *ptr,
                  const char *func,
                  const char *filename)
 {
-#ifdef NC_DEBUG
+#ifdef _DEBUG
     if (ptr == NULL)
 	fprintf(stderr, "Attempt to free null pointer in file %s, line %d\n", filename, lineno);
 #endif
diff --git a/src/lib/mpincio.c b/src/lib/mpincio.c
index 3398461..2952008 100644
--- a/src/lib/mpincio.c
+++ b/src/lib/mpincio.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: mpincio.c 2323 2016-02-26 23:04:46Z wkliao $ */
+/* $Id: mpincio.c 2520 2016-10-06 00:43:21Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #ifdef HAVE_ACCESS
@@ -51,6 +51,10 @@
 
 #define MAX_NC_ID 1024
 
+/* ncid corresponds to the index of IDalloc. The content of IDalloc[ncid] is
+ * either 0 or 1. 1 means ncid is corresponds to an opened file. 0 for
+ * otherwise. (not thread-safe)
+ */
 static unsigned char IDalloc[MAX_NC_ID];
 
 inline void
@@ -95,6 +99,9 @@ static
 void ncmpiio_extract_hints(ncio     *nciop,
                            MPI_Info  info)
 {
+    char value[MPI_MAX_INFO_VAL];
+    int  flag;
+
     /* value 0 indicates the hint is not set */
     nciop->hints.h_align                = 0;
     nciop->hints.v_align                = 0;
@@ -106,61 +113,58 @@ void ncmpiio_extract_hints(ncio     *nciop,
 #endif
 
     /* extract NC hints */
-    if (info != MPI_INFO_NULL) {
-        char value[MPI_MAX_INFO_VAL];
-        int  flag;
+    if (info == MPI_INFO_NULL) return;
 
-        MPI_Info_get(info, "nc_header_align_size", MPI_MAX_INFO_VAL-1, value,
-                     &flag);
-        if (flag) nciop->hints.h_align = atoll(value);
+    MPI_Info_get(info, "nc_header_align_size", MPI_MAX_INFO_VAL-1, value,
+                 &flag);
+    if (flag) nciop->hints.h_align = atoll(value);
 
-        MPI_Info_get(info, "nc_var_align_size",    MPI_MAX_INFO_VAL-1, value,
-                     &flag);
-        if (flag) nciop->hints.v_align = atoll(value);
+    MPI_Info_get(info, "nc_var_align_size",    MPI_MAX_INFO_VAL-1, value,
+                 &flag);
+    if (flag) nciop->hints.v_align = atoll(value);
 
-        MPI_Info_get(info, "nc_record_align_size", MPI_MAX_INFO_VAL-1,
-                     value, &flag);
-        if (flag) nciop->hints.r_align = atoll(value);
+    MPI_Info_get(info, "nc_record_align_size", MPI_MAX_INFO_VAL-1,
+                 value, &flag);
+    if (flag) nciop->hints.r_align = atoll(value);
 
-        MPI_Info_get(info, "nc_header_read_chunk_size", MPI_MAX_INFO_VAL-1,
-                     value, &flag);
-        if (flag) nciop->hints.header_read_chunk_size = atoll(value);
+    MPI_Info_get(info, "nc_header_read_chunk_size", MPI_MAX_INFO_VAL-1,
+                 value, &flag);
+    if (flag) nciop->hints.header_read_chunk_size = atoll(value);
 
 #ifdef ENABLE_SUBFILING
-        MPI_Info_get(info, "pnetcdf_subfiling", MPI_MAX_INFO_VAL-1,
-                     value, &flag);
-        if (flag && strcasecmp(value, "disable") == 0)
-            nciop->hints.subfile_mode = 0;
-
-        MPI_Info_get(info, "nc_num_subfiles", MPI_MAX_INFO_VAL-1,
-                     value, &flag);
-        if (flag) nciop->hints.num_subfiles = atoi(value);
+    MPI_Info_get(info, "pnetcdf_subfiling", MPI_MAX_INFO_VAL-1,
+                 value, &flag);
+    if (flag && strcasecmp(value, "disable") == 0)
+        nciop->hints.subfile_mode = 0;
+
+    MPI_Info_get(info, "nc_num_subfiles", MPI_MAX_INFO_VAL-1,
+                 value, &flag);
+    if (flag) nciop->hints.num_subfiles = atoi(value);
 #endif
 
-        /* nc_header_align_size, nc_var_align_size, and nciop->hints.r_align
-         * take effect when a file is created or opened and later adding more
-         * header or variable data */
-
-        if (nciop->hints.h_align < 0)
-            nciop->hints.h_align = 0;
-        if (nciop->hints.v_align < 0)
-            nciop->hints.v_align = 0;
-        if (nciop->hints.r_align < 0)
-            nciop->hints.r_align = 0;
-        if (nciop->hints.header_read_chunk_size < 0)
-            nciop->hints.header_read_chunk_size = 0;
+    /* nc_header_align_size, nc_var_align_size, and nciop->hints.r_align
+     * take effect when a file is created or opened and later adding more
+     * header or variable data */
+
+    if (nciop->hints.h_align < 0)
+        nciop->hints.h_align = 0;
+    if (nciop->hints.v_align < 0)
+        nciop->hints.v_align = 0;
+    if (nciop->hints.r_align < 0)
+        nciop->hints.r_align = 0;
+    if (nciop->hints.header_read_chunk_size < 0)
+        nciop->hints.header_read_chunk_size = 0;
 #ifdef ENABLE_SUBFILING
-        if (nciop->hints.num_subfiles < 0)
-            nciop->hints.num_subfiles = 0;
-        /* override subfile hints if env var is set */
-        char *num_sf_env;
-        num_sf_env = getenv("NC_NUM_SUBFILES");
-        if (num_sf_env != NULL)
-            nciop->hints.num_subfiles = atoi(num_sf_env);
-        if (nciop->hints.subfile_mode == 0)
-            nciop->hints.num_subfiles = 0;
+    if (nciop->hints.num_subfiles < 0)
+        nciop->hints.num_subfiles = 0;
+    /* override subfile hints if env var is set */
+    char *num_sf_env;
+    num_sf_env = getenv("NC_NUM_SUBFILES");
+    if (num_sf_env != NULL)
+        nciop->hints.num_subfiles = atoi(num_sf_env);
+    if (nciop->hints.subfile_mode == 0)
+        nciop->hints.num_subfiles = 0;
 #endif
-    }
 }
 
 /*----< ncmpiio_create() >---------------------------------------------------*/
@@ -175,13 +179,13 @@ ncmpiio_create(MPI_Comm     comm,
     int i, rank, mpireturn, err;
     int mpiomode = MPI_MODE_RDWR | MPI_MODE_CREATE;
 
-    assert(path != NULL);
-    assert(*path != '\0');
     /* checking path consistency is expected done in MPI-IO */
 
     MPI_Comm_rank(comm, &rank);
 
-    /* NC_CLOBBER is the default mode, even if it is not used in cmode */
+    /* NC_CLOBBER is the default mode, even if it is not used in cmode.
+     * Note ioflags has been checked for consistency before entering this API.
+     */
     if (fIsSet(ioflags, NC_NOCLOBBER)) {
         /* check if file exists: NetCDF requires NC_EEXIST returned if the file
          * already exists and NC_NOCLOBBER mode is used in create
@@ -241,16 +245,17 @@ ncmpiio_create(MPI_Comm     comm,
     /* ignore if NC_NOWRITE set by user */
     fSet(ioflags, NC_WRITE);
 
-    nciop = ncmpiio_new(path, ioflags); /* allocate buffer */
-    if (nciop == NULL)
-        DEBUG_RETURN_ERROR(NC_ENOMEM)
+    /* allocate ncio object */
+    nciop = ncmpiio_new(path, ioflags);
+    if (nciop == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
 
     nciop->mpiomode  = MPI_MODE_RDWR;
     nciop->mpioflags = 0;
 
-    /* extract MPI-IO hints */
+    /* intialize hints and extract PnetCDF-level hints */
     ncmpiio_extract_hints(nciop, info);
 
+    /* open file in parallel */
     TRACE_IO(MPI_File_open)(comm, (char *)path, mpiomode, info,
                             &nciop->collective_fh);
     if (mpireturn != MPI_SUCCESS) {
@@ -287,7 +292,7 @@ ncmpiio_create(MPI_Comm     comm,
         DEBUG_RETURN_ERROR(NC_ENFILE)
     }
 
-    *((int *)&nciop->fd) = i;
+    nciop->fd = i;
     IDalloc[i] = 1;
 
     /* collective I/O mode is the default mode */
@@ -299,7 +304,9 @@ ncmpiio_create(MPI_Comm     comm,
         return ncmpii_handle_error(mpireturn, "MPI_Comm_dup");
 
     /* get the file info actually used by MPI-IO (maybe alter user's info) */
-    MPI_File_get_info(nciop->collective_fh, &nciop->mpiinfo);
+    mpireturn = MPI_File_get_info(nciop->collective_fh, &nciop->mpiinfo);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_File_get_info");
 
     ncp->nciop = nciop;
     return NC_NOERR;
@@ -317,8 +324,11 @@ ncmpiio_open(MPI_Comm     comm,
     int i, mpireturn;
     int mpiomode = fIsSet(ioflags, NC_WRITE) ? MPI_MODE_RDWR : MPI_MODE_RDONLY;
 
-    assert(path != NULL);
-    assert(*path != '\0');
+    /* Note ioflags has been checked for consistency before entering this API.
+     */
+
+    assert(ncp != NULL);
+
     /* checking path consistency is expected done in MPI-IO */
 
     /* When open an non-existing file for read, we can either call access() to
@@ -338,40 +348,45 @@ ncmpiio_open(MPI_Comm     comm,
     }
 #endif
 
+    /* allocate ncio object */
     nciop = ncmpiio_new(path, ioflags);
-    if (nciop == NULL)
-        DEBUG_RETURN_ERROR(NC_ENOMEM)
+    if (nciop == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
 
     nciop->mpiomode  = mpiomode;
     nciop->mpioflags = 0;
 
-    /* extract MPI-IO hints */
+    /* intialize hints and extract PnetCDF-level hints */
     ncmpiio_extract_hints(nciop, info);
 
-    TRACE_IO(MPI_File_open)(comm, (char *)path, mpiomode,
-                            info, &nciop->collective_fh);
+    /* open file in parallel */
+    TRACE_IO(MPI_File_open)(comm, (char *)path, mpiomode, info,
+                            &nciop->collective_fh);
     if (mpireturn != MPI_SUCCESS) {
         ncmpiio_free(nciop);
         return ncmpii_handle_error(mpireturn, "MPI_File_open");
     }
 
+    /* check if max number of opened files is reached */
     for (i=0; i<MAX_NC_ID && IDalloc[i] != 0; i++);
     if (i == MAX_NC_ID) {
         ncmpiio_free(nciop);
         DEBUG_RETURN_ERROR(NC_ENFILE)
     }
-    *((int *)&nciop->fd) = i;
+    nciop->fd = i;
     IDalloc[i] = 1;
 
+    /* default mode is collective */
     set_NC_collectiveFh(nciop);
 
-    /* duplicate communicator as user may free it later */
+    /* duplicate MPI communicator as user may free it later */
     mpireturn = MPI_Comm_dup(comm, &(nciop->comm));
     if (mpireturn != MPI_SUCCESS)
         return ncmpii_handle_error(mpireturn, "MPI_Comm_dup");
 
     /* get the file info used by MPI-IO */
-    MPI_File_get_info(nciop->collective_fh, &nciop->mpiinfo);
+    mpireturn = MPI_File_get_info(nciop->collective_fh, &nciop->mpiinfo);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_File_get_info");
 
     ncp->nciop = nciop;
     return NC_NOERR;
@@ -420,7 +435,7 @@ ncmpiio_close(ncio *nciop, int doUnlink) {
         if (mpireturn != MPI_SUCCESS)
             return ncmpii_handle_error(mpireturn, "MPI_File_close");
     }
-    IDalloc[*((int *)&nciop->fd)] = 0;
+    IDalloc[nciop->fd] = 0;
 
     if (doUnlink) {
         TRACE_IO(MPI_File_delete)((char *)nciop->path, nciop->mpiinfo);
@@ -441,7 +456,7 @@ ncmpiio_move(ncio *const nciop,
 {
     int rank, nprocs, bufcount, mpireturn, err, status=NC_NOERR, min_st;
     void *buf;
-    int chunk_size = 1048576; /* move 1 MB per process at a time */
+    int chunk_size=1048576; /* move 1 MB per process at a time */
     MPI_Status mpistatus;
 
     MPI_Comm_size(nciop->comm, &nprocs);
@@ -451,6 +466,8 @@ ncmpiio_move(ncio *const nciop,
      * we use that instead of 1 MB */
     if (nciop->striping_unit > 0) chunk_size = nciop->striping_unit;
 
+    /* buf will be used as a temporal buffer to move data in chunks, i.e.
+     * read a chunk and later write to the new location */
     buf = NCI_Malloc((size_t)chunk_size);
     if (buf == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
 
@@ -460,6 +477,8 @@ ncmpiio_move(ncio *const nciop,
 
     /* move the variable starting from its tail toward its beginning */
     while (nbytes > 0) {
+        int get_size=0;
+
         /* calculate how much to move at each time */
         bufcount = chunk_size;
         if (nbytes < (MPI_Offset)nprocs * chunk_size) {
@@ -475,6 +494,9 @@ ncmpiio_move(ncio *const nciop,
             nbytes -= chunk_size*nprocs;
         }
 
+        /* explicitly initialize mpistatus object to 0, see comments below */
+        memset(&mpistatus, 0, sizeof(MPI_Status));
+
         /* read the original data @ from+nbytes+rank*chunk_size */
         TRACE_IO(MPI_File_read_at_all)(nciop->collective_fh,
                                        from+nbytes+rank*chunk_size,
@@ -484,7 +506,12 @@ ncmpiio_move(ncio *const nciop,
             if (err == NC_EFILE) DEBUG_ASSIGN_ERROR(status, NC_EREAD)
         }
         else {
-            int get_size;
+            /* for zero-length read, MPI_Get_count may report incorrect result
+             * for some MPICH version, due to the uninitialized MPI_Status
+             * object passed to MPI-IO calls. Thus we initialize it above to
+             * work around. Otherwise we can just use:
+            nciop->get_size += bufcount;
+             */
             MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
             nciop->get_size += get_size;
         }
@@ -495,15 +522,37 @@ ncmpiio_move(ncio *const nciop,
         status = min_st;
         if (status != NC_NOERR) break;
 
-        /* write to new location @ to+nbytes+rank*chunk_size */
+        /* write to new location @ to+nbytes+rank*chunk_size
+         *
+         * Ideally, we should write the amount of get_size returned from a call
+         * to MPI_Get_count in the below MPI write. This is in case some
+         * variables are defined but never been written. The value returned by
+         * MPI_Get_count is supposed to be the actual amount read by the MPI
+         * read call. If partial data (or none) is available for read, then we
+         * should just write that amount. Note this MPI write is collective,
+         * and thus all processes must participate the call even if get_size
+         * is 0. However, in some MPICH versions MPI_Get_count fails to report
+         * the correct value due to an internal error that fails to initialize
+         * the MPI_Status object. Therefore, the solution can be either to
+         * explicitly initialize the status object to zeros, or to just use
+         * bufcount for write. Note that the latter will write the variables
+         * that have not been written before. Below uses the former option.
+         */
         TRACE_IO(MPI_File_write_at_all)(nciop->collective_fh,
                                         to+nbytes+rank*chunk_size,
-                                        buf, bufcount, MPI_BYTE, &mpistatus);
+                                        buf, get_size /* bufcount */,
+                                        MPI_BYTE, &mpistatus);
         if (mpireturn != MPI_SUCCESS) {
             err = ncmpii_handle_error(mpireturn, "MPI_File_write_at_all");
             if (err == NC_EFILE) DEBUG_ASSIGN_ERROR(status, NC_EWRITE)
         }
         else {
+            /* for zero-length read, MPI_Get_count may report incorrect result
+             * for some MPICH version, due to the uninitialized MPI_Status
+             * object passed to MPI-IO calls. Thus we initialize it above to
+             * work around. Otherwise we can just use:
+            nciop->put_size += bufcount;
+             */
             int put_size;
             MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
             nciop->put_size += put_size;
diff --git a/src/lib/mpinetcdf.c b/src/lib/mpinetcdf.c
index cab7790..3aa8032 100644
--- a/src/lib/mpinetcdf.c
+++ b/src/lib/mpinetcdf.c
@@ -2,20 +2,22 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: mpinetcdf.c 2322 2016-02-26 22:47:06Z wkliao $ */
+/* $Id: mpinetcdf.c 2590 2016-10-31 21:37:02Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
-#include <unistd.h>
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
 #include <assert.h>
 #include <string.h>  /* strtok(), strcpy(), strchr() */
 #include <strings.h> /* strcasecmp() */
+#include <fcntl.h>   /* open() */
+#include <unistd.h>  /* read(), close() */
+#include <errno.h>   /* errno */
 
 #include <mpi.h>
 
@@ -29,10 +31,20 @@
 /* The const string below is for the RCS ident(1) command to find a string like
  * "\044Id: \100(#) PnetCDF library version 1.4.0 of 16 Nov 2013 $"
  * in the library file (libpnetcdf.a).
+ *
+ * This string must be made a global variable. Otherwise, it won't work
+ * when compiled with optimization options, e.g. -O2
  */
-static char const pnetcdf_libvers[] =
+char const pnetcdf_libvers[] =
         "\044Id: \100(#) PnetCDF library version "PNETCDF_VERSION" of "PNETCDF_RELEASE_DATE" $";
 
+/* a cleaner version for running command "strings", e.g.
+ * % strings libpnetcdf.a | grep "PnetCDF library version"
+ * or
+ * % strings a.out | grep "PnetCDF library version"
+ */
+char pnetcdf_lib_vers[] = "PnetCDF library version "PNETCDF_VERSION" of "PNETCDF_RELEASE_DATE;
+
 /* pnetcdf_libvers is slightly different from the one returned from
  * ncmpi_inq_libvers(). The string pnetcdf_libvers is for command "ident" to
  * use. People can run command ident libpnetcdf.a to obtain the version of a
@@ -145,7 +157,6 @@ hint indicates the chunk size (in bytes). The default is 256 KB.
 Can be use to check if the file exists.
 \returns ::NC_EMULTIDEFINE_OMODE Bad file create/open mode or modes are
 inconsistent across processes
-\returns ::NC_EOFILE: Can not open/create file (MPI-IO errors)
 \returns ::NC_EFILE: Unknown error in file operation
 
 <h1>Examples</h1>
@@ -196,13 +207,13 @@ ncmpi_create(MPI_Comm    comm,
              MPI_Info    info,
              int        *ncidp)
 {
-    int flag, err, status=NC_NOERR, safe_mode=0, mpireturn;
+    int i, err, status, safe_mode=0, mpireturn, default_format, root_cmode;
     char *env_str;
-    MPI_Info   env_info;
+    MPI_Info   env_info=MPI_INFO_NULL;
     MPI_Offset chunksize=NC_DEFAULT_CHUNKSIZE;
-    NC *ncp;
+    NC *ncp=NULL;
 
-#ifdef PNC_DEBUG
+#ifdef PNETCDF_DEBUG
     safe_mode = 1;
     /* this configure time setting will be overwritten by the run-time
      * environment variable PNETCDF_SAFE_MODE */
@@ -217,71 +228,100 @@ ncmpi_create(MPI_Comm    comm,
          * be '\0' (null character). In this case, safe_mode is enabled */
     }
 
-    if (safe_mode) {
-        /* check if cmode is consistent with root's */
-        int root_cmode=cmode;
+    /* path's validity is checked in MPI-IO with error code MPI_ERR_BAD_FILE
+     * path consistency is checked in MPI-IO with error code MPI_ERR_NOT_SAME
+     */
+    if (path == NULL || *path == '\0') DEBUG_RETURN_ERROR(NC_EBAD_FILE)
 
-        TRACE_COMM(MPI_Bcast)(&root_cmode, 1, MPI_INT, 0, comm);
-        if (mpireturn != MPI_SUCCESS)
-            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+    /* check default format */
+    ncmpi_inq_default_format(&default_format);
 
-        if (root_cmode != cmode) {
-            int rank;
-            MPI_Comm_rank(comm, &rank);
-            /* cmodes are inconsistent, overwrite local cmode with root's */
-            printf("rank %d: Warning - inconsistent file create mode, overwrite with root's\n",rank);
-            cmode = root_cmode;
-            DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_OMODE)
-        }
-        TRACE_COMM(MPI_Allreduce)(&status, &err, 1, MPI_INT, MPI_MIN, comm);
-        if (err != NC_NOERR) return status;
+    /* check if cmode is consistent with root's */
+    root_cmode = cmode;
+    TRACE_COMM(MPI_Bcast)(&root_cmode, 1, MPI_INT, 0, comm);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_Bcast");
 
-        /* when safe_mode is disabled, NC_EMULTIDEFINE_OMODE will be reported at
-         * the time ncmpi_enddef() returns */
+    /* only root's cmode matters */
+    status = NC_NOERR;
+    if (root_cmode != cmode) {
+        cmode = root_cmode;
+        DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_CMODE)
     }
 
+    if (safe_mode) { /* return now if cmode is inconsistent */
+        err = status;
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        if (status != NC_NOERR) return status;
+    } /* otherwise, use root's cmode to create file */
+
+#if SIZEOF_MPI_OFFSET <  8
+    /* check cmode */
+    if (fIsSet(cmode, NC_64BIT_DATA)     ||
+        fIsSet(cmode, NC_64BIT_OFFSET)   ||
+        default_format == NC_FORMAT_CDF5 || 
+        default_format == NC_FORMAT_CDF2) {
+        /* unlike serial netcdf, we will not bother to support
+         * NC_64BIT_OFFSET on systems with off_t smaller than 8 bytes.
+         * serial netcdf has proven it's possible if datasets are small, but
+         * that's a hassle we don't want to worry about */
+        DEBUG_RETURN_ERROR(NC_ESMALL)
+    }
+#endif
+
+    /* NC_DISKLESS is not supported yet */
+    if (cmode & NC_DISKLESS) DEBUG_RETURN_ERROR(NC_EINVAL_CMODE)
+
+    /* NC_MMAP is not supported yet */
+    if (cmode & NC_MMAP) DEBUG_RETURN_ERROR(NC_EINVAL_CMODE)
+
     /* It is illegal to have both NC_64BIT_OFFSET & NC_64BIT_DATA */
     if ((cmode & (NC_64BIT_OFFSET|NC_64BIT_DATA)) ==
-                 (NC_64BIT_OFFSET|NC_64BIT_DATA))
-        DEBUG_ASSIGN_ERROR(status, NC_EINVAL_CMODE)
-    /* In safe_mode, cmodes are sync-ed, so all processes can return the same
-     * error code. But, when not in safe mode, if cmode is not consistent
-     * among processes, then some processes might not violate this above rule
-     * which can cause the program to hang (because MPI_File_open is a
-     * collective call). We use MPI_Allreduce below to check the error
-     * code, but it is costly.
-     */
-    if (safe_mode) {
-        TRACE_COMM(MPI_Allreduce)(&status, &err, 1, MPI_INT, MPI_MIN, comm);
-        status = err;
+                 (NC_64BIT_OFFSET|NC_64BIT_DATA)) {
+        DEBUG_RETURN_ERROR(NC_EINVAL_CMODE)
     }
-    if (status != NC_NOERR) return status;
 
     /* take hints from the environment variable PNETCDF_HINTS
      * a string of hints separated by ";" and each hint is in the
      * form of hint=value. E.g. cb_nodes=16;cb_config_list=*:6
-     * If this environment variable is set, it  overrides any values that
+     * If this environment variable is set, it overrides any values that
      * were set by using calls to MPI_Info_set in the application code.
      */
-    env_info = info;
+    if (info != MPI_INFO_NULL) {
+#ifdef HAVE_MPI_INFO_DUP
+        mpireturn = MPI_Info_dup(info, &env_info);
+        if (mpireturn != MPI_SUCCESS)
+            DEBUG_RETURN_ERROR(ncmpii_handle_error(mpireturn, "MPI_Info_dup"))
+#else
+        printf("Warning: MPI info is ignored as MPI_Info_dup() is missing\n");
+#endif
+    }
     if ((env_str = getenv("PNETCDF_HINTS")) != NULL) {
         if (env_info == MPI_INFO_NULL)
             MPI_Info_create(&env_info); /* ignore error */
 
-        char *key = strtok(env_str, ";");
+        char *env_str_cpy, *key;
+        env_str_cpy = (char*) NCI_Malloc(strlen(env_str)+1);
+        strcpy(env_str_cpy, env_str);
+        key = strtok(env_str_cpy, ";");
         while (key != NULL) {
             char *val;
             val = strchr(key, '=');
+            if (val == NULL) continue; /* ill-formed hint */
             *val = '\0';
             val++;
             /* printf("env hint: key=%s val=%s\n",key,val); */
             MPI_Info_set(env_info, key, val); /* override or add */
             key = strtok(NULL, ";");
         }
+        NCI_Free(env_str_cpy);
     }
 
     /* get header chunk size from user info */
     if (env_info != MPI_INFO_NULL) {
+        int flag;
         char value[MPI_MAX_INFO_VAL];
         MPI_Info_get(env_info, "nc_header_read_chunk_size", MPI_MAX_INFO_VAL-1,
                      value, &flag);
@@ -289,8 +329,11 @@ ncmpi_create(MPI_Comm    comm,
     }
 
     /* allocate buffer for header object NC */
-    if ((ncp = ncmpii_new_NC(&chunksize)) == NULL)
+    ncp = ncmpii_new_NC(&chunksize);
+    if (ncp == NULL) {
+        if (env_info != MPI_INFO_NULL) MPI_Info_free(&env_info);
         DEBUG_RETURN_ERROR(NC_ENOMEM)
+    }
 
     ncp->safe_mode = safe_mode;
     ncp->abuf      = NULL;
@@ -298,6 +341,7 @@ ncmpi_create(MPI_Comm    comm,
 #ifdef ENABLE_SUBFILING
     ncp->subfile_mode = 1;
     if (env_info != MPI_INFO_NULL) {
+        int flag;
         char value[MPI_MAX_INFO_VAL];
         MPI_Info_get(env_info, "pnetcdf_subfiling", MPI_MAX_INFO_VAL-1,
                      value, &flag);
@@ -307,63 +351,71 @@ ncmpi_create(MPI_Comm    comm,
     ncp->ncid_sf = -1; /* subfile ncid; init to -1 */
     ncp->nc_num_subfiles = 0; /* num_subfiles; init to 0 */
 #endif
-    assert(ncp->flags == 0);
 
     /* set the file format version based on the create mode, cmode */
     if (fIsSet(cmode, NC_64BIT_DATA)) {
-#if SIZEOF_MPI_OFFSET <  8
-        DEBUG_RETURN_ERROR(NC_ESMALL)
-#endif
         fSet(ncp->flags, NC_64BIT_DATA);
+        ncp->format = 5;
     } else if (fIsSet(cmode, NC_64BIT_OFFSET)) {
-        /* unlike serial netcdf, we will not bother to support
-         * NC_64BIT_OFFSET on systems with off_t smaller than 8 bytes.
-         * serial netcdf has proven it's possible if datasets are small, but
-         * that's a hassle we don't want to worry about */
-        if (SIZEOF_OFF_T < 8) DEBUG_RETURN_ERROR(NC_ESMALL)
         fSet(ncp->flags, NC_64BIT_OFFSET);
+        ncp->format = 2;
     } else {
-        /* check default format */
-        int default_format;
-        ncmpi_inq_default_format(&default_format);
         if (default_format == NC_FORMAT_CDF5) {
-#if SIZEOF_MPI_OFFSET <  8
-            DEBUG_RETURN_ERROR(NC_ESMALL)
-#endif
             fSet(ncp->flags, NC_64BIT_DATA);
+            ncp->format = 5;
         }
         else if (default_format == NC_FORMAT_CDF2) {
-            if (SIZEOF_OFF_T < 8) DEBUG_RETURN_ERROR(NC_ESMALL)
             fSet(ncp->flags, NC_64BIT_OFFSET);
+            ncp->format = 2;
         }
-        else
+        else {
             fSet(ncp->flags, NC_32BIT);
+            ncp->format = 1;
+        }
     }
 
     /* find the true header size (not-yet aligned) */
     ncp->xsz = ncmpii_hdr_len_NC(ncp);
 
+    /* PnetCDF default fill mode is no fill */
     fSet(ncp->flags, NC_NOFILL);
 
+    /* open file collectively */
     err = ncmpiio_create(comm, path, cmode, env_info, ncp);
     if (err != NC_NOERR) { /* fatal error */
+        if (err == NC_EMULTIDEFINE_OMODE) err = NC_EMULTIDEFINE_CMODE;
+        if (env_info != MPI_INFO_NULL) MPI_Info_free(&env_info);
         ncmpii_free_NC(ncp);
-        return err;
+        DEBUG_RETURN_ERROR(err)
     }
 
     fSet(ncp->flags, NC_CREAT);
 
-    /* the linked list storing the outstanding non-blocking requests */
-    ncp->head = NULL;
-    ncp->tail = NULL;
+    /* initialize arrays storing pending non-blocking requests */
     ncp->numGetReqs = 0;
     ncp->numPutReqs = 0;
+    ncp->get_list   = NULL;
+    ncp->put_list   = NULL;
 
     /* add to the linked list of opened files */
     ncmpii_add_to_NCList(ncp);
     *ncidp = ncp->nciop->fd;
 
-    if (env_info != info) MPI_Info_free(&env_info);
+    if (env_info != MPI_INFO_NULL) MPI_Info_free(&env_info);
+
+    /* initialize unlimited_id as no unlimited dimension yet defined */
+    ncp->dims.unlimited_id = -1;
+
+#ifndef SEARCH_NAME_LINEARLY
+    for (i=0; i<HASH_TABLE_SIZE; i++) {
+        /* initialize dim name lookup table */
+        ncp->dims.nameT[i].num = 0;
+        ncp->dims.nameT[i].list = NULL;
+        /* initialize var name lookup table */
+        ncp->vars.nameT[i].num = 0;
+        ncp->vars.nameT[i].list = NULL;
+    }
+#endif
 
     return status;
 }
@@ -376,13 +428,16 @@ ncmpi_open(MPI_Comm    comm,
            MPI_Info    info,
            int        *ncidp)
 {
-    int i, flag, err, status=NC_NOERR, safe_mode=0, mpireturn;
+    int i, err, status, safe_mode=0, mpireturn, root_omode;
     char *env_str;
-    MPI_Info   env_info;
+    MPI_Info   env_info=MPI_INFO_NULL;
     MPI_Offset chunksize=NC_DEFAULT_CHUNKSIZE;
-    NC *ncp;
+    NC *ncp=NULL;
+#ifndef SEARCH_NAME_LINEARLY
+    NC_nametable *nameT;
+#endif
 
-#ifdef PNC_DEBUG
+#ifdef PNETCDF_DEBUG
     safe_mode = 1;
     /* this configure time setting will be overwritten by the run-time
      * environment variable PNETCDF_SAFE_MODE */
@@ -397,68 +452,100 @@ ncmpi_open(MPI_Comm    comm,
          * be '\0' (null character). In this case, safe_mode is enabled */
     }
 
-    if (safe_mode) {
-        /* check if omode is consistent with root's */
-        int root_omode=omode;
+    /* path's validity is checked in MPI-IO with error code MPI_ERR_BAD_FILE
+     * path consistency is checked in MPI-IO with error code MPI_ERR_NOT_SAME
+     */
+    if (path == NULL || *path == '\0') DEBUG_RETURN_ERROR(NC_EBAD_FILE)
 
-        /* Note if omode contains NC_NOWRITE, it is equivalent to NC_CLOBBER.
-           In pnetcdf.h, they both are defined the same value, 0.
-         */
+    /* check if omode is consistent with root's */
 
-        TRACE_COMM(MPI_Bcast)(&root_omode, 1, MPI_INT, 0, comm);
-        if (mpireturn != MPI_SUCCESS)
-            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+    /* Note if omode contains NC_NOWRITE, it is equivalent to NC_CLOBBER.
+     * In pnetcdf.h, they both are defined the same value, 0.
+     * Only root's omode matters.
+     */
+    root_omode = omode;
+    TRACE_COMM(MPI_Bcast)(&root_omode, 1, MPI_INT, 0, comm);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_Bcast");
 
-        if (root_omode != omode) {
-            int rank;
-            MPI_Comm_rank(comm, &rank);
-            /* omodes are inconsistent, overwrite local omode with root's */
-            printf("rank %d: Warning - inconsistent file open mode, overwrite with root's\n",rank);
-            omode = root_omode;
-            DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_OMODE)
-        }
+    status = NC_NOERR;
+    if (root_omode != omode) {
+        omode = root_omode;
+        DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_OMODE)
     }
 
+    if (safe_mode) { /* return now if omode is inconsistent */
+        err = status;
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        if (status != NC_NOERR) return status;
+    } /* otherwise, use root's omode to open file */
+
+    /* NC_DISKLESS is not supported yet */
+    if (omode & NC_DISKLESS) DEBUG_RETURN_ERROR(NC_EINVAL_OMODE)
+
+    /* NC_MMAP is not supported yet */
+    if (omode & NC_MMAP) DEBUG_RETURN_ERROR(NC_EINVAL_OMODE)
+
     /* take hints from the environment variable PNETCDF_HINTS
      * a string of hints separated by ";" and each hint is in the
      * form of hint=value. E.g. cb_nodes=16;cb_config_list=*:6
      * If this environment variable is set, it  overrides any values that
      * were set by using calls to MPI_Info_set in the application code.
      */
-    env_info = info;
+    if (info != MPI_INFO_NULL) {
+#ifdef HAVE_MPI_INFO_DUP
+        mpireturn = MPI_Info_dup(info, &env_info);
+        if (mpireturn != MPI_SUCCESS)
+            DEBUG_RETURN_ERROR(ncmpii_handle_error(mpireturn, "MPI_Info_dup"))
+#else
+        printf("Warning: MPI info is ignored as MPI_Info_dup() is missing\n");
+#endif
+    }
     if ((env_str = getenv("PNETCDF_HINTS")) != NULL) {
         if (env_info == MPI_INFO_NULL)
             MPI_Info_create(&env_info); /* ignore error */
 
-        char *key = strtok(env_str, ";");
+        char *env_str_cpy, *key;
+        env_str_cpy = (char*) NCI_Malloc(strlen(env_str)+1);
+        strcpy(env_str_cpy, env_str);
+        key = strtok(env_str_cpy, ";");
         while (key != NULL) {
             char *val;
             val = strchr(key, '=');
+            if (val == NULL) continue; /* ill-formed hint */
             *val = '\0';
             val++;
             /* printf("env hint: key=%s val=%s\n",key,val); */
             MPI_Info_set(env_info, key, val); /* override or add */
             key = strtok(NULL, ";");
         }
+        NCI_Free(env_str_cpy);
     }
 
     /* get header chunk size from user info, if provided */
     if (env_info != MPI_INFO_NULL) {
+        int flag;
         char value[MPI_MAX_INFO_VAL];
         MPI_Info_get(env_info, "nc_header_read_chunk_size", MPI_MAX_INFO_VAL-1,
                      value, &flag);
         if (flag) chunksize = atoll(value);
     }
 
+    /* allocate NC file object */
     ncp = ncmpii_new_NC(&chunksize);
-    if (ncp == NULL)
+    if (ncp == NULL) {
+        if (env_info != MPI_INFO_NULL) MPI_Info_free(&env_info);
         DEBUG_RETURN_ERROR(NC_ENOMEM)
+    }
 
     ncp->safe_mode = safe_mode;
     ncp->old       = NULL;
 #ifdef ENABLE_SUBFILING
     ncp->subfile_mode = 1;
     if (env_info != MPI_INFO_NULL) {
+        int flag;
         char value[MPI_MAX_INFO_VAL];
         MPI_Info_get(env_info, "pnetcdf_subfiling", MPI_MAX_INFO_VAL-1,
                      value, &flag);
@@ -469,26 +556,33 @@ ncmpi_open(MPI_Comm    comm,
     ncp->nc_num_subfiles = 0;
 #endif
 
+    /* open the file in parallel */
     err = ncmpiio_open(comm, path, omode, env_info, ncp);
     if (err != NC_NOERR) { /* fatal error */
+        if (env_info != MPI_INFO_NULL) MPI_Info_free(&env_info);
         ncmpii_free_NC(ncp);
-        return err;
+        DEBUG_RETURN_ERROR(err)
     }
 
-    assert(ncp->flags == 0);
+    /* PnetCDF's default mode is no fill */
     fSet(ncp->flags, NC_NOFILL);
 
-    err = ncmpii_hdr_get_NC(ncp); /* read header from file */
+    /* read header from file into an NC object pointed by ncp */
+    err = ncmpii_hdr_get_NC(ncp);
     if (err != NC_NOERR) { /* fatal error */
         ncmpiio_close(ncp->nciop, 0);
+        if (env_info != MPI_INFO_NULL) MPI_Info_free(&env_info);
         ncmpii_free_NC(ncp);
-        return err;
+        DEBUG_RETURN_ERROR(err)
     }
-    ncp->head = NULL;
-    ncp->tail = NULL;
+
+    /* initialize arrays storing pending non-blocking requests */
     ncp->numGetReqs = 0;
     ncp->numPutReqs = 0;
+    ncp->get_list   = NULL;
+    ncp->put_list   = NULL;
 
+    /* add NC object to the linked list of opened files */
     ncmpii_add_to_NCList(ncp);
     *ncidp = ncp->nciop->fd;
 
@@ -537,10 +631,45 @@ ncmpi_open(MPI_Comm    comm,
     for (i=0; i<ncp->vars.ndefined; i++)
         ncp->vars.num_rec_vars += IS_RECVAR(ncp->vars.value[i]);
 
+#ifndef SEARCH_NAME_LINEARLY
+    /* initialize dim name lookup table */
+    nameT = ncp->dims.nameT;
+    memset(nameT, 0, sizeof(NC_nametable) * HASH_TABLE_SIZE);
+
+    /* populate dim name lookup table */
+    for (i=0; i<ncp->dims.ndefined; i++) {
+        /* hash the dim name into a key for name lookup */
+        int key = HASH_FUNC(ncp->dims.value[i]->name->cp);
+        nameT = &ncp->dims.nameT[key];
+        if (nameT->num % NC_NAME_TABLE_CHUNK == 0)
+            nameT->list = (int*) NCI_Realloc(nameT->list,
+                          (size_t)(nameT->num+NC_NAME_TABLE_CHUNK) * sizeof(int));
+        nameT->list[nameT->num] = i;
+        nameT->num++;
+    }
+
+    /* initialize var name lookup table */
+    nameT = ncp->vars.nameT;
+    memset(nameT, 0, sizeof(NC_nametable) * HASH_TABLE_SIZE);
+
+    /* populate var name lookup table */
+    for (i=0; i<ncp->vars.ndefined; i++) {
+        /* hash the var name into a key for name lookup */
+        int key = HASH_FUNC(ncp->vars.value[i]->name->cp);
+        nameT = &ncp->vars.nameT[key];
+        if (nameT->num % NC_NAME_TABLE_CHUNK == 0)
+            nameT->list = (int*) NCI_Realloc(nameT->list,
+                          (size_t)(nameT->num+NC_NAME_TABLE_CHUNK) * sizeof(int));
+        nameT->list[nameT->num] = i;
+        nameT->num++;
+    }
+#endif
+
     return status;
 }
 
 /*----< ncmpi_inq_format() >-------------------------------------------------*/
+/* This is an independent subroutine. */
 int
 ncmpi_inq_format(int  ncid,
                  int *formatp) /* out */
@@ -552,57 +681,102 @@ ncmpi_inq_format(int  ncid,
     if (status != NC_NOERR)
         return status;
 
-    if (fIsSet(ncp->flags, NC_64BIT_DATA)) {
+    if (ncp->format == 5) {
         *formatp = NC_FORMAT_CDF5;
-    } else if (fIsSet(ncp->flags, NC_64BIT_OFFSET)) {
+    } else if (ncp->format == 2) {
         *formatp = NC_FORMAT_CDF2;
-    } else if (fIsSet(ncp->flags, NC_32BIT)){
+    } else if (ncp->format == 1) {
         *formatp = NC_FORMAT_CLASSIC;
     } else {
-        /* this should not happen, because if ncid is valid, checking for
-         * valid CDF format should have already been done already */
+        /* this should not happen, because if ncid is valid, checking whether
+         * the file is in a supported CDF format should have already been done
+         * at ncmpi_open or ncmpi_create
+         */
         *formatp = NC_FORMAT_UNKNOWN;
     }
     return status;
 }
 
 /*----< ncmpi_inq_file_format() >--------------------------------------------*/
+/* This is an independent subroutine. */
 int
 ncmpi_inq_file_format(char *filename,
                       int  *formatp) /* out */
 {
+#ifdef _USE_NCMPI
     int ncid, status;
     NC *ncp;
 
     /* open file for reading its header */
     status = ncmpi_open(MPI_COMM_SELF, filename, NC_NOWRITE, MPI_INFO_NULL,
                         &ncid);
-    if (status == NC_ENOTNC)
-        DEBUG_ASSIGN_ERROR(*formatp, NC_FORMAT_UNKNOWN)
-    if (status != NC_NOERR)
+    if (status != NC_NOERR) {
+        if (status == NC_ENOTNC3)
+            DEBUG_ASSIGN_ERROR(*formatp, NC_FORMAT_NETCDF4)
+        else if (status == NC_ENOTNC)
+            DEBUG_ASSIGN_ERROR(*formatp, NC_FORMAT_UNKNOWN)
         return status;
+    }
 
     status = ncmpii_NC_check_id(ncid, &ncp);
     if (status != NC_NOERR)
          return status;
 
-    if (fIsSet(ncp->flags, NC_64BIT_DATA)) {
+    if (ncp->format == 5) {
         *formatp = NC_FORMAT_CDF5;
-    } else if (fIsSet(ncp->flags, NC_64BIT_OFFSET)) {
+    } else if (ncp->format == 2) {
         *formatp = NC_FORMAT_CDF2;
-    } else if (fIsSet(ncp->flags, NC_32BIT)){
+    } else {  /* if (ncp->format == 1) */
         *formatp = NC_FORMAT_CLASSIC;
-    } else {
-        /* this should not happen, because if ncid is valid, checking for
-         * valid CDF format should have already been done already */
-        *formatp = NC_FORMAT_UNKNOWN;
     }
     status = ncmpi_close(ncid);
 
     return status;
+#else
+    char *cdf_signature="CDF";
+    char *hdf5_signature="\211HDF\r\n\032\n";
+    char signature[8];
+    int fd;
+    ssize_t rlen;
+
+    *formatp = NC_FORMAT_UNKNOWN;
+
+    if ((fd = open(filename, O_RDONLY, 0700)) == -1) {
+             if (errno == ENOENT)       return NC_ENOENT;
+        else if (errno == EACCES)       return NC_EACCESS;
+        else if (errno == ENAMETOOLONG) return NC_EBAD_FILE;
+        else                            return NC_EFILE;
+    }
+    /* get first 8 bytes of file */
+    rlen = read(fd, signature, 8);
+    if (rlen != 8) {
+        close(fd); /* ignore error */
+        return NC_EFILE;
+    }
+    if (close(fd) == -1) {
+        return NC_EFILE;
+    }
+
+    if (memcmp(signature, hdf5_signature, 8) == 0) {
+        /* whether the file is NC_FORMAT_NETCDF4_CLASSIC is determined by HDF5
+         * attribute "_nc3_strict" which requires a call to H5Aget_name(). Here
+         * we do not distinquish NC_CLASSIC_MODEL, but simply return NETCDF4
+         * format.
+         */
+        *formatp = NC_FORMAT_NETCDF4;
+    }
+    else if (memcmp(signature, cdf_signature, 3) == 0) {
+             if (signature[3] == 5)  *formatp = NC_FORMAT_CDF5;
+        else if (signature[3] == 2)  *formatp = NC_FORMAT_CDF2;
+        else if (signature[3] == 1)  *formatp = NC_FORMAT_CLASSIC;
+    }
+
+    return NC_NOERR;
+#endif
 }
 
 /*----< ncmpi_inq_file_info() >-----------------------------------------------*/
+/* This is an independent subroutine. */
 int
 ncmpi_inq_file_info(int       ncid,
                     MPI_Info *info_used)
@@ -648,6 +822,7 @@ ncmpi_inq_file_info(int       ncid,
 }
 
 /*----< ncmpi_get_file_info() >-----------------------------------------------*/
+/* This is an independent subroutine. */
 int
 ncmpi_get_file_info(int       ncid,
                     MPI_Info *info_used)
@@ -656,6 +831,7 @@ ncmpi_get_file_info(int       ncid,
 }
 
 /*----< ncmpi_redef() >------------------------------------------------------*/
+/* This is a collective subroutine. */
 int
 ncmpi_redef(int ncid) {
     int status;
@@ -669,7 +845,7 @@ ncmpi_redef(int ncid) {
     /* if open mode is inconsistent, then this return might cause parallel
      * program to hang */
 
-    /* cannot be in define mode */
+    /* cannot be in define mode, must enter from data mode */
     if (NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_EINDEFINE)
 
     /* sync all metadata, including numrecs, if changed in independent mode.
@@ -683,7 +859,7 @@ ncmpi_redef(int ncid) {
         if (status != NC_NOERR) return status;
     }
 
-    /* duplicate a header to be uses in enddef() for checking if header grows */
+    /* duplicate a header to be used in enddef() for checking if header grows */
     ncp->old = ncmpii_dup_NC(ncp);
     if (ncp->old == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
 
@@ -694,6 +870,7 @@ ncmpi_redef(int ncid) {
 }
 
 /*----< ncmpi_begin_indep_data() >-------------------------------------------*/
+/* This is a collective subroutine. */
 int
 ncmpi_begin_indep_data(int ncid)
 {
@@ -734,6 +911,7 @@ ncmpi_begin_indep_data(int ncid)
 }
 
 /*----< ncmpi_end_indep_data() >---------------------------------------------*/
+/* This is a collective subroutine. */
 int
 ncmpi_end_indep_data(int ncid) {
     int status;
@@ -781,6 +959,8 @@ ncmpii_end_indep_data(NC *ncp)
                 if (status == NC_NOERR) status = err;
             }
             TRACE_COMM(MPI_Barrier)(ncp->nciop->comm);
+            if (mpireturn != MPI_SUCCESS)
+                return ncmpii_handle_error(mpireturn, "MPI_Barrier");
         }
 #endif
     }
@@ -791,6 +971,7 @@ ncmpii_end_indep_data(NC *ncp)
 }
 
 /*----< ncmpi_enddef() >-----------------------------------------------------*/
+/* This is a collective subroutine. */
 int
 ncmpi_enddef(int ncid) {
     int status;
@@ -807,6 +988,7 @@ ncmpi_enddef(int ncid) {
 }
 
 /*----< ncmpi__enddef() >-----------------------------------------------------*/
+/* This is a collective subroutine. */
 int
 ncmpi__enddef(int        ncid,
               MPI_Offset h_minfree,
@@ -814,16 +996,44 @@ ncmpi__enddef(int        ncid,
               MPI_Offset v_minfree,
               MPI_Offset r_align)
 {
-    int status;
+    int err;
     NC *ncp;
 
     /* check if file ID ncid is valid */
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
     if (!NC_indef(ncp)) /* must currently in define mode */
         DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
 
+    if (ncp->safe_mode) {
+        int status, mpireturn;
+        MPI_Offset root_args[4];
+
+        /* check if h_minfree, v_align, v_minfree, and r_align are consistent
+         * among all processes */
+        root_args[0] = h_minfree;
+        root_args[1] = v_align;
+        root_args[2] = v_minfree;
+        root_args[3] = r_align;
+        TRACE_COMM(MPI_Bcast)(&root_args, 4, MPI_OFFSET, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+
+        if (root_args[0] != h_minfree ||
+            root_args[1] != v_align   ||
+            root_args[2] != v_minfree ||
+            root_args[3] != r_align)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FNC_ARGS)
+
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+
+        if (status != NC_NOERR) return status;
+    }
+
     return ncmpii__enddef(ncp, h_minfree, v_align, v_minfree, r_align);
 }
 
@@ -868,14 +1078,16 @@ ncmpi_sync_numrecs(int ncid) {
             if (status == NC_NOERR) status = err;
         }
         TRACE_COMM(MPI_Barrier)(ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Barrier");
     }
 #endif
     return status;
 }
 
 /*----< ncmpi_sync() >--------------------------------------------------------*/
-/* This API must be called collectively, no matter if it is in collective
- * or independent data mode.
+/* This API is a collective subroutine, and must be called in data mode, no
+ * matter if it is in collective or independent data mode.
  */
 int
 ncmpi_sync(int ncid) {
@@ -885,6 +1097,7 @@ ncmpi_sync(int ncid) {
     status = ncmpii_NC_check_id(ncid, &ncp);
     if (status != NC_NOERR) return status;
 
+    /* cannot be in define mode */
     if (NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_EINDEFINE)
 
     if (NC_readonly(ncp))
@@ -905,12 +1118,13 @@ ncmpi_sync(int ncid) {
 }
 
 /*----< ncmpi_abort() >------------------------------------------------------*/
+/* This API is a collective subroutine */
 int
 ncmpi_abort(int ncid) {
    /*
     * In data mode, same as ncmpiio_close.
     * In define mode, descard new definition.
-    * In create, remove the file.
+    * If file is just created, remove the file.
     */
     int status, err, doUnlink = 0;
     NC *ncp;
@@ -958,6 +1172,7 @@ ncmpi_abort(int ncid) {
 }
 
 /*----< ncmpi_close() >------------------------------------------------------*/
+/* This is a collective subroutine. */
 int
 ncmpi_close(int ncid) {
     int status = NC_NOERR;
@@ -1030,6 +1245,7 @@ ncmpii_check_mpifh(NC  *ncp,
 }
 
 /*----< ncmpi_inq_put_size() >------------------------------------------------*/
+/* This is an independent subroutine. */
 /* returns the amount of writes, in bytes, committed to file system so far */
 int
 ncmpi_inq_put_size(int         ncid,
@@ -1047,6 +1263,7 @@ ncmpi_inq_put_size(int         ncid,
 }
 
 /*----< ncmpi_inq_get_size() >------------------------------------------------*/
+/* This is an independent subroutine. */
 /* returns the amount of reads, in bytes, obtained from file system so far */
 int
 ncmpi_inq_get_size(int         ncid,
@@ -1064,7 +1281,8 @@ ncmpi_inq_get_size(int         ncid,
 }
 
 /*----< ncmpi_inq_striping() >------------------------------------------------*/
-/* return file (system) striping settings, striping size and count, if they are
+/* This is an independent subroutine.
+ * return file (system) striping settings, striping size and count, if they are
  * available from MPI-IO hint. Otherwise, 0s are returned.
  */
 int
@@ -1097,7 +1315,8 @@ ncmpi_inq_striping(int  ncid,
 }
 
 /*----< ncmpi_inq_malloc_size() >--------------------------------------------*/
-/* report the current aggregate size allocated by malloc, yet to be freed */
+/* This is an independent subroutine.
+ * report the current aggregate size allocated by malloc, yet to be freed */
 int ncmpi_inq_malloc_size(MPI_Offset *size)
 {
 #ifdef PNC_MALLOC_TRACE
@@ -1109,7 +1328,8 @@ int ncmpi_inq_malloc_size(MPI_Offset *size)
 }
 
 /*----< ncmpi_inq_malloc_max_size() >----------------------------------------*/
-/* get the max watermark ever researched by malloc (aggregated amount) */
+/* This is an independent subroutine.
+ * get the max watermark ever researched by malloc (aggregated amount) */
 int ncmpi_inq_malloc_max_size(MPI_Offset *size)
 {
 #ifdef PNC_MALLOC_TRACE
@@ -1121,7 +1341,8 @@ int ncmpi_inq_malloc_max_size(MPI_Offset *size)
 }
 
 /*----< ncmpi_inq_malloc_list() >--------------------------------------------*/
-/* walk the malloc tree and print yet-to-be-freed malloc residues */
+/* This is an independent subroutine.
+ * walk the malloc tree and print yet-to-be-freed malloc residues */
 int ncmpi_inq_malloc_list(void)
 {
 #ifdef PNC_MALLOC_TRACE
@@ -1133,6 +1354,7 @@ int ncmpi_inq_malloc_list(void)
 }
 
 /*----< ncmpi_inq_files_opened() >-------------------------------------------*/
+/* This is an independent subroutine. */
 int
 ncmpi_inq_files_opened(int *num, int *ncids)
 {
@@ -1140,6 +1362,7 @@ ncmpi_inq_files_opened(int *num, int *ncids)
 }
 
 /*----< ncmpi_inq_recsize() >------------------------------------------------*/
+/* This is an independent subroutine. */
 int
 ncmpi_inq_recsize(int         ncid,
                   MPI_Offset *recsize)
@@ -1156,6 +1379,7 @@ ncmpi_inq_recsize(int         ncid,
 }
 
 /*----< ncmpi_inq_header_extent() >-------------------------------------------*/
+/* This is an independent subroutine. */
 int
 ncmpi_inq_header_extent(int         ncid,
                         MPI_Offset *extent)
@@ -1172,6 +1396,7 @@ ncmpi_inq_header_extent(int         ncid,
 }
 
 /*----< ncmpi_inq_header_size() >---------------------------------------------*/
+/* This is an independent subroutine. */
 int
 ncmpi_inq_header_size(int         ncid,
                       MPI_Offset *size)
diff --git a/src/lib/nc.c b/src/lib/nc.c
index 7bc11ca..9f4adff 100644
--- a/src/lib/nc.c
+++ b/src/lib/nc.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: nc.c 2326 2016-03-01 17:21:03Z wkliao $ */
+/* $Id: nc.c 2604 2016-11-09 16:10:48Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #ifdef HAVE_STDLIB_H
@@ -25,11 +25,13 @@
 #include "subfile.h"
 #endif
 
-/* list of open netcdf's */
+/* list of opened netcdf file objects (not thread-safe) */
 static NC *NClist = NULL;
 
-/* This is the default create format for ncmpi_create and nc__create. */
-static int default_create_format = NC_FORMAT_CLASSIC;
+/* This is the default create format for ncmpi_create and nc__create.
+ * The use of this file scope variable is not thread-safe.
+ */
+static int ncmpi_default_create_format = NC_FORMAT_CLASSIC;
 
 /* These have to do with version numbers. */
 #define MAGIC_NUM_LEN 4
@@ -43,7 +45,6 @@ static int default_create_format = NC_FORMAT_CLASSIC;
 static int move_data_r(NC *ncp, NC *old);
 static int move_vars_r(NC *ncp, NC *old);
 static int NC_check_def(MPI_Comm comm, void *buf, MPI_Offset nn);
-static int nc_set_fill(int ncid, int fillmode, int *old_mode_ptr);
 #endif
 
 /*----< ncmpii_add_to_NCList() >---------------------------------------------*/
@@ -82,6 +83,7 @@ ncmpii_del_from_NCList(NC *ncp)
     ncp->prev = NULL;
 }
 
+#ifdef _CHECK_HEADER_IN_DETAIL
 /*----< NC_check_header() >--------------------------------------------------*/
 /*
  * Check the consistency of defined header metadata across all processes and
@@ -93,72 +95,75 @@ NC_check_header(NC         *ncp,
                 void       *buf,
                 MPI_Offset  local_xsz) /* size of buf */
 {
-    void *cmpbuf;
-    int rank, g_status, status=NC_NOERR, mpireturn;
-    bufferinfo gbp;
-
-    MPI_Comm_rank(ncp->nciop->comm, &rank);
+    int h_size, rank, g_status, status=NC_NOERR, mpireturn;
 
     /* root's header size has been broadcasted in NC_begin() and saved in
      * ncp->xsz.
      */
-    if (rank == 0)
-        cmpbuf = buf;
-    else
-        cmpbuf = (void*) NCI_Malloc((size_t)ncp->xsz);
 
-    /* process 0 broadcasts its header
-     * TODO: currently the header size cannot be larger than 2^31 bytes,
+    /* TODO: When root process 0 broadcasts its header,
+     * currently the header size cannot be larger than 2^31 bytes,
      * due to the 2nd argument, count, of MPI_Bcast being of type int.
      * Possible solution is to broadcast in chunks of 2^31 bytes.
      */
-    if (ncp->xsz != (int)ncp->xsz) {
-        if (rank > 0) NCI_Free(cmpbuf);
+    h_size = (int)ncp->xsz;
+    if (ncp->xsz != h_size)
         DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
-    }
-
-    TRACE_COMM(MPI_Bcast)(cmpbuf, (int)ncp->xsz, MPI_BYTE, 0, ncp->nciop->comm);
 
-    if (rank > 0 && (ncp->xsz != local_xsz || memcmp(buf, cmpbuf, (size_t)ncp->xsz))) {
-        /* now part of this process's header is not consistent with root's
-         * check and report the inconsistent part
-         */
-
-        gbp.nciop  = ncp->nciop; /* will not be used in ncmpii_hdr_check_NC() */
-        gbp.offset = 0;          /* will not be used in ncmpii_hdr_check_NC() */
-        gbp.size   = ncp->xsz;   /* entire header is in the buffer, cmpbuf */
-        gbp.index  = 0;
-        gbp.pos    = gbp.base = cmpbuf;
-
-        /* find the inconsistent part of the header, report the difference, and
-         * overwrite the local header object with root's. ncmpii_hdr_check_NC()
-         * should not have any MPI communication calls.
-         */
-        status = ncmpii_hdr_check_NC(&gbp, ncp);
+    MPI_Comm_rank(ncp->nciop->comm, &rank);
 
-        /* header consistency is only checked on non-root processes. The
-         * returned status can be a fatal error or header inconsistency error,
-         * (fatal errors are due to object allocation), but never NC_NOERR.
-         */
+    if (rank == 0) {
+        TRACE_COMM(MPI_Bcast)(buf, h_size, MPI_BYTE, 0, ncp->nciop->comm);
+    }
+    else {
+        bufferinfo gbp;
+        void *cmpbuf = (void*) NCI_Malloc((size_t)h_size);
+
+        TRACE_COMM(MPI_Bcast)(cmpbuf, h_size, MPI_BYTE, 0, ncp->nciop->comm);
+
+        if (h_size != local_xsz || memcmp(buf, cmpbuf, h_size)) {
+            /* now part of this process's header is not consistent with root's
+             * check and report the inconsistent part
+             */
+
+            /* Note that gbp.nciop and gbp.offset below will not be used in
+             * ncmpii_hdr_check_NC() */
+            gbp.nciop  = ncp->nciop;
+            gbp.offset = 0;
+            gbp.size   = h_size;   /* entire header is in the buffer, cmpbuf */
+            gbp.index  = 0;
+            gbp.pos    = gbp.base = cmpbuf;
+
+            /* find the inconsistent part of the header, report the difference,
+             * and overwrite the local header object with root's.
+             * ncmpii_hdr_check_NC() should not have any MPI communication
+             * calls.
+             */
+            status = ncmpii_hdr_check_NC(&gbp, ncp);
+
+            /* header consistency is only checked on non-root processes. The
+             * returned status can be a fatal error or header inconsistency
+             * error, (fatal errors are due to object allocation), but never
+             * NC_NOERR.
+             */
+        }
+        NCI_Free(cmpbuf);
     }
 
     if (ncp->safe_mode) {
         TRACE_COMM(MPI_Allreduce)(&status, &g_status, 1, MPI_INT, MPI_MIN,
                                   ncp->nciop->comm);
         if (mpireturn != MPI_SUCCESS) {
-            if (rank > 0) NCI_Free(cmpbuf);
             return ncmpii_handle_error(mpireturn, "MPI_Allreduce"); 
         }
-
         if (g_status != NC_NOERR) { /* some headers are inconsistent */
             if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE)
         }
     }
 
-    if (rank > 0) NCI_Free(cmpbuf);
-
     return status;
 }
+#endif
 
 
 #if 0
@@ -218,7 +223,7 @@ ncmpii_NC_check_id(int   ncid,
     if (ncid >= 0) {
         for (ncp = NClist; ncp != NULL; ncp = ncp->next) {
             if (ncp->nciop->fd == ncid) {
-                *ncpp = ncp;
+                if (ncpp != NULL) *ncpp = ncp;
                 return NC_NOERR; /* normal return */
             }
         }
@@ -260,9 +265,11 @@ inline void
 ncmpii_free_NC(NC *ncp)
 {
     if (ncp == NULL) return;
+
     ncmpii_free_NC_dimarray(&ncp->dims);
     ncmpii_free_NC_attrarray(&ncp->attrs);
     ncmpii_free_NC_vararray(&ncp->vars);
+
     NCI_Free(ncp);
 }
 
@@ -283,42 +290,16 @@ ncmpii_new_NC(const MPI_Offset *chunkp)
 /*----< ncmpi_set_default_format() >-----------------------------------------*/
 /* This function sets a default create file format.
  * Valid formats are NC_FORMAT_CLASSIC, NC_FORMAT_CDF2, and NC_FORMAT_CDF5
- * This API is collective.
+ * This API is NOT collective, as there is no way to check against an MPI
+ * communicator. It should be called by all MPI processes that intend to
+ * create a file later. Consistency check will have to be done in other APIs.
  */
 int
 ncmpi_set_default_format(int format, int *old_formatp)
 {
-    int safe_mode=0, mpireturn, status=NC_NOERR;
-    char *env_str;
-
     /* Return existing format if desired. */
-    if (old_formatp)
-        *old_formatp = default_create_format;
-
-    env_str = getenv("PNETCDF_SAFE_MODE");
-    if (env_str != NULL) {
-        if (*env_str == '0') safe_mode = 0;
-        else                 safe_mode = 1;
-    }
-
-    if (safe_mode) {
-        /* check if format is consistent with root's */
-        int root_format=format;
-
-        TRACE_COMM(MPI_Bcast)(&root_format, 1, MPI_INT, 0, MPI_COMM_WORLD);
-        if (mpireturn != MPI_SUCCESS)
-            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
-
-        if (root_format != format) {
-            int rank;
-            MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-            /* formats are inconsistent, overwrite local format with root's */
-            printf("rank %d: Warning - inconsistent file format, overwrite with root's\n",rank);
-            format = root_format;
-            DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_OMODE)
-        }
-    }
-
+    if (old_formatp != NULL)
+        *old_formatp = ncmpi_default_create_format;
 
     /* Make sure only valid format is set. */
     if (format != NC_FORMAT_CLASSIC &&
@@ -326,9 +307,9 @@ ncmpi_set_default_format(int format, int *old_formatp)
         format != NC_FORMAT_CDF5) {
         DEBUG_RETURN_ERROR(NC_EINVAL)
     }
-    default_create_format = format;
+    ncmpi_default_create_format = format;
 
-    return status;
+    return NC_NOERR;
 }
 
 /* returns a value suitable for a create flag.  Will return one or more of the
@@ -339,7 +320,7 @@ ncmpi_inq_default_format(int *formatp)
 {
     if (formatp == NULL) DEBUG_RETURN_ERROR(NC_EINVAL)
 
-    *formatp = default_create_format;
+    *formatp = ncmpi_default_create_format;
     return NC_NOERR;
 }
 
@@ -439,27 +420,36 @@ NC_begins(NC         *ncp,
           MPI_Offset  v_minfree,/* free space for fixed variable section */
           MPI_Offset  r_align)  /* alignment for record variable section */
 {
-    int i, j, rank, cdf_format, mpireturn;
+    int i, j, rank, mpireturn;
     MPI_Offset end_var=0;
     NC_var *last = NULL;
     NC_var *first_var = NULL;       /* first "non-record" var */
 
-    /* cdf_format determines the size of variable's "begin" in the header */
-    if (fIsSet(ncp->flags, NC_64BIT_DATA))
-        cdf_format = 5;  /* CDF-5 */
-    else if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
-        cdf_format = 2;  /* CDF-2 */
-    else
-        cdf_format = 1;  /* CDF-1 */
+    /* CDF file format determines the size of variable's "begin" in the header */
 
-    /* get the true header size (un-aligned one) */
+    /* get the true header size (not header extent) */
     MPI_Comm_rank(ncp->nciop->comm, &rank);
-    if (rank ==0) ncp->xsz = ncmpii_hdr_len_NC(ncp);
+    ncp->xsz = ncmpii_hdr_len_NC(ncp);
 
-    /* only root's header size matters */
-    TRACE_COMM(MPI_Bcast)(&ncp->xsz, 1, MPI_OFFSET, 0, ncp->nciop->comm);
-    if (mpireturn != MPI_SUCCESS)
-        return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+    if (ncp->safe_mode) { /* this consistency check is redundant as metadata is
+                             kept consistent at all time when safe mode is on */
+        int err, status;
+        MPI_Offset root_xsz = ncp->xsz;
+
+        /* only root's header size matters */
+        TRACE_COMM(MPI_Bcast)(&root_xsz, 1, MPI_OFFSET, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+
+        err = NC_NOERR;
+        if (root_xsz != ncp->xsz) err = NC_EMULTIDEFINE;
+
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        if (status != NC_NOERR) DEBUG_RETURN_ERROR(status)
+    }
 
     /* This function is called in ncmpi_enddef(), which can happen either when
      * creating a new file or opening an existing file with metadata modified.
@@ -495,7 +485,7 @@ NC_begins(NC         *ncp,
         if (first_var == NULL) first_var = ncp->vars.value[i];
 
         /* for CDF-1 check if over the file size limit 32-bit integer */
-        if (cdf_format == 1 && end_var > X_OFF_MAX)
+        if (ncp->format == 1 && end_var > X_OFF_MAX)
             DEBUG_RETURN_ERROR(NC_EVARSIZE)
 
         /* this will pad out non-record variables with zero to the
@@ -569,7 +559,7 @@ NC_begins(NC         *ncp,
             continue;
 
         /* X_OFF_MAX is the max of 32-bit integer */
-        if (cdf_format == 1 && end_var > X_OFF_MAX)
+        if (ncp->format == 1 && end_var > X_OFF_MAX)
             DEBUG_RETURN_ERROR(NC_EVARSIZE)
 
         /* A few attempts at aligning record variables have failed
@@ -593,7 +583,7 @@ NC_begins(NC         *ncp,
         end_var += ncp->vars.value[i]->len;
         /* end_var is the end offset of record variable i */
 
-        /* check if record size must fit in 32-bits */
+        /* check if record size must fit in 32-bits (for CDF-1) */
 #if SIZEOF_OFF_T == SIZEOF_SIZE_T && SIZEOF_SIZE_T == 4
         if (ncp->recsize > X_UINT_MAX - ncp->vars.value[i]->len)
             DEBUG_RETURN_ERROR(NC_EVARSIZE)
@@ -639,94 +629,116 @@ NC_begins(NC         *ncp,
 
 #define NC_NUMRECS_OFFSET 4
 
-/*----< ncmpii_sync_numrecs() >-----------------------------------------------*/
-/* Synchronize the number of records in memory and write numrecs to file.
+/*----< ncmpii_write_numrecs() >-----------------------------------------------*/
+/* root process writes the new record number into file.
  * This function is called by:
- * 1. ncmpi_sync_numrecs(): by the user
- * 2. ncmpi_sync(): by the user
- * 3. ncmpii_end_indep_data(): exit from independent data mode
- * 4. all blocking collective put APIs (getput.m4) when writing record variable
- * 5. collective nonblocking wait API (ncmpii_wait_getput)
- * 6. ncmpii_close(): file close and currently in independent data mode
- *
- * This function is collective.
+ * 1. ncmpii_sync_numrecs
+ * 2. collective nonblocking wait API, if the new number of records is bigger
  */
 int
-ncmpii_sync_numrecs(NC         *ncp,
-                    MPI_Offset  new_numrecs)
+ncmpii_write_numrecs(NC         *ncp,
+                     MPI_Offset  new_numrecs)
 {
-    int rank, status=NC_NOERR, mpireturn, err;
+    int rank, mpireturn, err;
     MPI_File fh;
-    MPI_Offset max_numrecs;
 
-    assert(!NC_readonly(ncp));
-    assert(!NC_indef(ncp)); /* can only be called by APIs in data mode */
+    /* root process writes numrecs in file */
+    MPI_Comm_rank(ncp->nciop->comm, &rank);
+    if (rank > 0) return NC_NOERR;
 
-    /* find the max new_numrecs among all processes
-     * Note new_numrecs may be smaller than ncp->numrecs
-     */
-    TRACE_COMM(MPI_Allreduce)(&new_numrecs, &max_numrecs, 1, MPI_OFFSET,
-                              MPI_MAX, ncp->nciop->comm);
-    if (mpireturn != MPI_SUCCESS)
-        return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+    /* return now if there is no record variabled defined */
+    if (ncp->vars.num_rec_vars == 0) return NC_NOERR;
 
     fh = ncp->nciop->collective_fh;
     if (NC_indep(ncp))
         fh = ncp->nciop->independent_fh;
 
-    /* root process writes numrecs in file */
-    MPI_Comm_rank(ncp->nciop->comm, &rank);
-    if (rank == 0 && /* Only root process writes to file header */
-        (max_numrecs > ncp->numrecs || NC_ndirty(ncp))) {
-         /* For collective data mode, we check max_numrecs against root's
-          * ncp->numrecs because root's numrecs has not been updated.
-          * For independent data mode, we check NC_ndirty bit, because root's
-          * numrecs may have been updated and in this case NC_ndirty bit has
-          * been set to dirty. */
+    if (new_numrecs > ncp->numrecs || NC_ndirty(ncp)) {
         int len;
         char pos[8], *buf=pos;
+        MPI_Offset max_numrecs;
         MPI_Status mpistatus;
 
-        if (ncp->flags & NC_64BIT_DATA) {
-            len = X_SIZEOF_INT64;
-            err = ncmpix_put_uint64((void**)&buf, max_numrecs);
-            if (status == NC_NOERR) status = err;
-        }
-        else {
-            if (max_numrecs != (int)max_numrecs) DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+        max_numrecs = MAX(new_numrecs, ncp->numrecs);
+
+        if (ncp->format < 5) {
+            if (max_numrecs != (int)max_numrecs)
+                DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
             len = X_SIZEOF_SIZE_T;
             err = ncmpix_put_uint32((void**)&buf, (uint)max_numrecs);
-            if (status == NC_NOERR) status = err;
+            if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+        }
+        else {
+            len = X_SIZEOF_INT64;
+            err = ncmpix_put_uint64((void**)&buf, (uint64)max_numrecs);
+            if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
         }
         /* ncmpix_put_xxx advances the 1st argument with size len */
 
         /* root's file view always includes the entire file header */
-
         TRACE_IO(MPI_File_write_at)(fh, NC_NUMRECS_OFFSET, (void*)pos, len,
                                     MPI_BYTE, &mpistatus);
         if (mpireturn != MPI_SUCCESS) {
             err = ncmpii_handle_error(mpireturn, "MPI_File_write_at");
-            if (status == NC_NOERR && err == NC_EFILE) DEBUG_ASSIGN_ERROR(status, NC_EWRITE)
+            if (err == NC_EFILE) DEBUG_RETURN_ERROR(NC_EWRITE)
         }
         else {
-            int put_size;
-            MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
-            ncp->nciop->put_size += put_size;
+            ncp->nciop->put_size += len;
         }
     }
-    /* update numrecs in all processes's memory only if the new one is larger.
+    return NC_NOERR;
+}
+
+/*----< ncmpii_sync_numrecs() >-----------------------------------------------*/
+/* Synchronize the number of records in memory and write numrecs to file.
+ * This function is called by:
+ * 1. ncmpi_sync_numrecs(): by the user
+ * 2. ncmpi_sync(): by the user
+ * 3. ncmpii_end_indep_data(): exit from independent data mode
+ * 4. all blocking collective put APIs when writing record variables
+ * 5. ncmpii_close(): file close and currently in independent data mode
+ *
+ * This function is collective.
+ */
+int
+ncmpii_sync_numrecs(NC         *ncp,
+                    MPI_Offset  new_numrecs)
+{
+    int status=NC_NOERR, mpireturn;
+    MPI_Offset max_numrecs;
+
+    assert(!NC_readonly(ncp));
+    assert(!NC_indef(ncp)); /* can only be called by APIs in data mode */
+
+    /* return now if there is no record variabled defined */
+    if (ncp->vars.num_rec_vars == 0) return NC_NOERR;
+
+    /* find the max new_numrecs among all processes
      * Note new_numrecs may be smaller than ncp->numrecs
      */
-    if (max_numrecs > ncp->numrecs) ncp->numrecs = max_numrecs;
+    TRACE_COMM(MPI_Allreduce)(&new_numrecs, &max_numrecs, 1, MPI_OFFSET,
+                              MPI_MAX, ncp->nciop->comm);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+
+    /* root process writes max_numrecs to file */
+    status = ncmpii_write_numrecs(ncp, max_numrecs);
 
     if (ncp->safe_mode == 1) {
         /* broadcast root's status, because only root writes to the file */
         int root_status = status;
         TRACE_COMM(MPI_Bcast)(&root_status, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
         /* root's write has failed, which is serious */
         if (root_status == NC_EWRITE) DEBUG_ASSIGN_ERROR(status, NC_EWRITE)
     }
 
+    /* update numrecs in all processes's memory only if the new one is larger.
+     * Note new_numrecs may be smaller than ncp->numrecs
+     */
+    if (max_numrecs > ncp->numrecs) ncp->numrecs = max_numrecs;
+
     /* clear numrecs dirty bit */
     fClr(ncp->flags, NC_NDIRTY);
 
@@ -768,14 +780,22 @@ static int
 write_NC(NC *ncp)
 {
     void *buf;
-    int status, mpireturn, err, max_err, rank;
+    int status, mpireturn, err, rank;
     MPI_Offset local_xsz;
 
     assert(!NC_readonly(ncp));
 
-    /* ncp->xsz is root's header size, we need to calculate local's */
+    /* In NC_begins(), root's ncp->xsz, root's header size, has been
+     * broadcasted, so ncp->xsz is now root's header size. To check any
+     * inconsistency in file header, we need to calculate local's header
+     * size by calling ncmpii_hdr_len_NC()./
+     */
     local_xsz = ncmpii_hdr_len_NC(ncp);
 
+    /* Note valgrind will complain about uninitialized buf below, but buf will
+     * be first filled with header of size ncp->xsz and later write to file.
+     * So, no need to change to NCI_Calloc for the sake of valgrind.
+     */
     buf = NCI_Malloc((size_t)local_xsz); /* buffer for local header object */
 
     /* copy the entire local header object to buffer */
@@ -785,6 +805,46 @@ write_NC(NC *ncp)
         return status;
     }
 
+    MPI_Comm_rank(ncp->nciop->comm, &rank);
+
+#ifdef _DIFF_HEADER
+    if (ncp->safe_mode == 0) {
+        int h_size=(int)ncp->xsz;
+        void *root_header;
+
+        /* check header against root's */
+        if (rank == 0)
+            root_header = buf;
+        else
+            root_header = (void*) NCI_Malloc((size_t)h_size);
+
+        TRACE_COMM(MPI_Bcast)(root_header, h_size, MPI_BYTE, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+
+        if (rank > 0) {
+            if (h_size != local_xsz || memcmp(buf, root_buf, h_size))
+                status = NC_EMULTIDEFINE;
+            NCI_Free(root_buf);
+        }
+
+        /* report error if header is inconsistency */
+        TRACE_COMM(MPI_Allreduce)(&status, &err, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            ncmpii_handle_error(mpireturn,"MPI_Allreduce");
+            DEBUG_RETURN_ERROR(NC_EMPI)
+        }
+        if (err != NC_NOERR) {
+            /* TODO: this error return is harsh. Maybe relax for inconsistent
+             * attribute contents? */
+            if (status == NC_NOERR) status = err;
+            NCI_Free(buf);
+            return status;
+        }
+    }
+#endif
+
+#ifdef _CHECK_HEADER_IN_DETAIL
     /* check the header consistency across all processes and sync header.
      * When safe_mode is on:
      *   The returned status on root can be either NC_NOERR (all headers are
@@ -797,6 +857,7 @@ write_NC(NC *ncp)
      *   error (>-250), or inconsistency error (-250 to -269).
      * For fatal error, we should stop. For others, we can continue.
      */
+    int max_err;
     status = NC_check_header(ncp, buf, local_xsz);
 
     /* check for fatal error */
@@ -811,20 +872,21 @@ write_NC(NC *ncp)
             DEBUG_RETURN_ERROR(NC_EMPI)
         }
     }
-
     if (max_err == 1) { /* some processes encounter a fatal error */
         NCI_Free(buf);
         return status;
     }
+#endif
     /* For non-fatal error, we continue to write header to the file, as now the
      * header object in memory has been sync-ed across all processes. */
 
     /* only rank 0's header gets written to the file */
-    MPI_Comm_rank(ncp->nciop->comm, &rank);
     if (rank == 0) {
         /* rank 0's fileview already includes the file header */
         MPI_Status mpistatus;
-        if (ncp->xsz != (int)ncp->xsz) DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+        if (ncp->xsz != (int)ncp->xsz)
+            DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+
         TRACE_IO(MPI_File_write_at)(ncp->nciop->collective_fh, 0, buf,
                                     (int)ncp->xsz, MPI_BYTE, &mpistatus);
         if (mpireturn != MPI_SUCCESS) {
@@ -833,9 +895,7 @@ write_NC(NC *ncp)
             if (err == NC_EFILE) DEBUG_ASSIGN_ERROR(status, NC_EWRITE)
         }
         else {
-            int put_size;
-            MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
-            ncp->nciop->put_size += put_size;
+            ncp->nciop->put_size += ncp->xsz;
         }
     }
 
@@ -940,7 +1000,9 @@ move_vars_r(NC *ncp, NC *old) {
 #endif
 
 /*
- * Given a valid ncp, return NC_EVARSIZE if any variable has a bad len
+ * Given a valid ncp, check all variables for their sizes against the maximal
+ * allowable sizes. Different CDF formation versions have different maximal
+ * sizes. This function returns NC_EVARSIZE if any variable has a bad len
  * (product of non-rec dim sizes too large), else return NC_NOERR.
  */
 static int
@@ -950,76 +1012,81 @@ ncmpii_NC_check_vlens(NC *ncp)
     /* maximum permitted variable size (or size of one record's worth
        of a record variable) in bytes.  This is different for format 1
        and format 2. */
-    MPI_Offset vlen_max;
-    MPI_Offset ii;
-    MPI_Offset large_vars_count;
-    MPI_Offset rec_vars_count;
+    MPI_Offset ii, vlen_max, rec_vars_count;
+    MPI_Offset large_fix_vars_count, large_rec_vars_count;
     int last = 0;
 
-    if(ncp->vars.ndefined == 0)
-       return NC_NOERR;
+    if (ncp->vars.ndefined == 0)
+        return NC_NOERR;
 
-    if ((ncp->flags & NC_64BIT_DATA) && SIZEOF_OFF_T > 4)
-       return NC_NOERR;
+    if (ncp->format >= 5) /* CDF-5 */
+        return NC_NOERR;
 
-    if ((ncp->flags & NC_64BIT_OFFSET) && SIZEOF_OFF_T > 4) {
-       /* CDF2 format and LFS */
-       vlen_max = X_UINT_MAX - 3; /* "- 3" handles rounded-up size */
-    } else {
-       /* CDF1 format */
-       vlen_max = X_INT_MAX - 3;
-    }
-    /* Loop through vars, first pass is for non-record variables.   */
-    large_vars_count = 0;
+    /* only CDF-1 and CDF-2 need to continue */
+
+    if (ncp->flags & NC_64BIT_OFFSET) /* CDF2 format */
+        vlen_max = X_UINT_MAX - 3; /* "- 3" handles rounded-up size */
+    else
+        vlen_max = X_INT_MAX - 3; /* CDF1 format */
+
+    /* Loop through vars, first pass is for non-record variables */
+    large_fix_vars_count = 0;
     rec_vars_count = 0;
     vpp = ncp->vars.value;
     for (ii = 0; ii < ncp->vars.ndefined; ii++, vpp++) {
-       if( !IS_RECVAR(*vpp) ) {
-           last = 0;
-           if( ncmpii_NC_check_vlen(*vpp, vlen_max) == 0 ) {
-               large_vars_count++;
-               last = 1;
-           }
-       } else {
-         rec_vars_count++;
-       }
+        if (!IS_RECVAR(*vpp)) {
+            last = 0;
+            if (ncmpii_NC_check_vlen(*vpp, vlen_max) == 0) {
+                /* check this variable's shape product against vlen_max */
+                large_fix_vars_count++;
+                last = 1;
+            }
+        } else {
+            rec_vars_count++;
+        }
     }
     /* OK if last non-record variable size too large, since not used to
        compute an offset */
-    if( large_vars_count > 1) { /* only one "too-large" variable allowed */
-      DEBUG_RETURN_ERROR(NC_EVARSIZE)
+    if (large_fix_vars_count > 1)  /* only one "too-large" variable allowed */
+        DEBUG_RETURN_ERROR(NC_EVARSIZE)
+
+    /* The only "too-large" variable must be the last one defined */
+    if (large_fix_vars_count == 1 && last == 0)
+        DEBUG_RETURN_ERROR(NC_EVARSIZE)
+
+    if (rec_vars_count == 0) return NC_NOERR;
+
+    /* if there is a "too-large" fixed-size variable, no record variable is
+     * allowed */
+    if (large_fix_vars_count == 1)
+        DEBUG_RETURN_ERROR(NC_EVARSIZE)
+
+    /* Loop through vars, second pass is for record variables.   */
+    large_rec_vars_count = 0;
+    vpp = ncp->vars.value;
+    for (ii = 0; ii < ncp->vars.ndefined; ii++, vpp++) {
+        if (IS_RECVAR(*vpp)) {
+            last = 0;
+            if (ncmpii_NC_check_vlen(*vpp, vlen_max) == 0) {
+                /* check this variable's shape product against vlen_max */
+                large_rec_vars_count++;
+                last = 1;
+            }
+        }
     }
+
+    /* For CDF-2, no record variable can require more than 2^32 - 4 bytes of
+     * storage for each record's worth of data, unless it is the last record
+     * variable. See
+     * http://www.unidata.ucar.edu/software/netcdf/docs/file_structure_and_performance.html#offset_format_limitations
+     */
+    if (large_rec_vars_count > 1)  /* only one "too-large" variable allowed */
+        DEBUG_RETURN_ERROR(NC_EVARSIZE)
+
     /* and it has to be the last one */
-    if( large_vars_count == 1 && last == 0) {
-      DEBUG_RETURN_ERROR(NC_EVARSIZE)
-    }
-    if( rec_vars_count > 0 ) {
-       /* and if it's the last one, there can't be any record variables */
-       if( large_vars_count == 1 && last == 1) {
-           DEBUG_RETURN_ERROR(NC_EVARSIZE)
-       }
-       /* Loop through vars, second pass is for record variables.   */
-       large_vars_count = 0;
-       vpp = ncp->vars.value;
-       for (ii = 0; ii < ncp->vars.ndefined; ii++, vpp++) {
-           if( IS_RECVAR(*vpp) ) {
-               last = 0;
-               if( ncmpii_NC_check_vlen(*vpp, vlen_max) == 0 ) {
-                   large_vars_count++;
-                   last = 1;
-               }
-           }
-       }
-       /* OK if last record variable size too large, since not used to
-          compute an offset */
-       if( large_vars_count > 1) { /* only one "too-large" variable allowed */
-           DEBUG_RETURN_ERROR(NC_EVARSIZE)
-       }
-       /* and it has to be the last one */
-       if( large_vars_count == 1 && last == 0) {
-           DEBUG_RETURN_ERROR(NC_EVARSIZE)
-       }
-    }
+    if (large_rec_vars_count == 1 && last == 0)
+        DEBUG_RETURN_ERROR(NC_EVARSIZE)
+
     return NC_NOERR;
 }
 
@@ -1099,7 +1166,7 @@ ncmpii_NC_enddef(NC         *ncp,
     }
 #endif
 
-    /* check on dimension lengths */
+    /* check whether sizes of all variables are legal */
     status = ncmpii_NC_check_vlens(ncp);
     CHECK_ERROR(status)
 
@@ -1108,6 +1175,9 @@ ncmpii_NC_enddef(NC         *ncp,
      * file offset as well as the offsets of record variables.
      * When ncp->old != NULL, this enddef is called after a redef. In this
      * case, we re-used all variable offsets as many as possible.
+     *
+     * Note in NC_begins, root broadcasts ncp->xsz, the file header size, to
+     * all processes.
      */
     status = NC_begins(ncp, h_align, h_minfree, v_align, v_minfree, r_align);
     CHECK_ERROR(status)
@@ -1160,8 +1230,8 @@ ncmpii_NC_enddef(NC         *ncp,
     } /* ... ncp->old != NULL */
 
     /* first sync header objects in memory across all processes, and then root
-     * writes the header to file. Note safe_mode error check is already done
-     * in write_NC() */
+     * writes the header to file. Note safe_mode error check will be done in
+     * write_NC() */
     status = write_NC(ncp);
 
     /* we should continue to exit define mode, even if header is inconsistent
@@ -1184,8 +1254,10 @@ ncmpii_NC_enddef(NC         *ncp,
         ncp->vars.num_rec_vars += IS_RECVAR(ncp->vars.value[i]);
 
     /* fill variables according to their fill mode settings */
-    err = ncmpii_fill_vars(ncp);
-    if (status == NC_NOERR) status = err;
+    if (ncp->vars.ndefined > 0) {
+        err = ncmpii_fill_vars(ncp);
+        if (status == NC_NOERR) status = err;
+    }
 
     if (ncp->old != NULL) {
         ncmpii_free_NC(ncp->old);
@@ -1218,6 +1290,9 @@ ncmpii_inq_env_align_hints(MPI_Offset *h_align,
                            MPI_Offset *h_chunk,
                            MPI_Offset *r_align)
 {
+    /* TODO: env variables have been checked in ncmpi_create and ncmpi_open
+     * Maybe this can be part of that
+     */
     char *env_str;
 
     *h_align = 0;
@@ -1226,9 +1301,13 @@ ncmpii_inq_env_align_hints(MPI_Offset *h_align,
     *r_align = 0;
 
     if ((env_str = getenv("PNETCDF_HINTS")) != NULL) {
-        char *key = strtok(env_str, ";");
+        char *env_str_cpy, *key;
+        env_str_cpy = (char*) NCI_Malloc(strlen(env_str)+1);
+        strcpy(env_str_cpy, env_str);
+        key = strtok(env_str_cpy, ";");
         while (key != NULL) {
             char *val = strchr(key, '=');
+            if (val == NULL) continue; /* ill-formed hint */
             *val = '\0';
             val++;
             if (strcasecmp(key, "nc_header_align_size") == 0)
@@ -1241,6 +1320,7 @@ ncmpii_inq_env_align_hints(MPI_Offset *h_align,
                 *r_align = atoll(val);
             key = strtok(NULL, ";");
         }
+        NCI_Free(env_str_cpy);
     }
     return 1;
 }
@@ -1438,13 +1518,31 @@ ncmpii_close(NC *ncp)
 
     /* We can cancel or complete all outstanding nonblocking I/O.
      * For now, cancelling makes more sense. */
-    if (ncp->head != NULL) {
 #ifdef COMPLETE_NONBLOCKING_IO
-        ncmpii_wait(ncp, INDEP_IO, NC_REQ_ALL, NULL, NULL);
+    if (ncp->numGetReqs > 0) {
+        ncmpii_wait(ncp, INDEP_IO, NC_GET_REQ_ALL, NULL, NULL);
+        if (status == NC_NOERR ) status = NC_EPENDING;
+    }
+    if (ncp->numPutReqs > 0) {
+        ncmpii_wait(ncp, INDEP_IO, NC_PUT_REQ_ALL, NULL, NULL);
+        if (status == NC_NOERR ) status = NC_EPENDING;
+    }
 #else
-        ncmpii_cancel(ncp, NC_REQ_ALL, NULL, NULL);
-#endif
+    if (ncp->numGetReqs > 0) {
+        int rank;
+        MPI_Comm_rank(ncp->nciop->comm, &rank);
+        printf("PnetCDF warning: %d nonblocking get requests still pending on process %d. Cancelling ...\n",ncp->numGetReqs,rank);
+        ncmpii_cancel(ncp, NC_GET_REQ_ALL, NULL, NULL);
+        if (status == NC_NOERR ) status = NC_EPENDING;
     }
+    if (ncp->numPutReqs > 0) {
+        int rank;
+        MPI_Comm_rank(ncp->nciop->comm, &rank);
+        printf("PnetCDF warning: %d nonblocking put requests still pending on process %d. Cancelling ...\n",ncp->numPutReqs,rank);
+        ncmpii_cancel(ncp, NC_PUT_REQ_ALL, NULL, NULL);
+        if (status == NC_NOERR ) status = NC_EPENDING;
+    }
+#endif
 
     /* If the user wants a stronger data consistency by setting NC_SHARE */
     if (fIsSet(ncp->nciop->ioflags, NC_SHARE))
@@ -1486,7 +1584,8 @@ ncmpi_inq(int  ncid,
     if (nattsp != NULL)
         *nattsp = (int) ncp->attrs.ndefined;
     if (xtendimp != NULL)
-        *xtendimp = ncmpii_find_NC_Udim(&ncp->dims, NULL);
+        /* *xtendimp = ncmpii_find_NC_Udim(&ncp->dims, NULL); */
+        *xtendimp = ncp->dims.unlimited_id;
 
     return NC_NOERR;
 }
@@ -1502,9 +1601,9 @@ ncmpi_inq_version(int ncid, int *nc_mode)
     if (status != NC_NOERR)
         return status;
 
-    if (fIsSet(ncp->flags, NC_64BIT_DATA))
+    if (ncp->format == 5)
         *nc_mode = NC_64BIT_DATA;
-    else if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
+    else if (ncp->format == 2)
         *nc_mode = NC_64BIT_OFFSET;
     else
         *nc_mode = NC_CLASSIC_MODEL;
@@ -1567,8 +1666,10 @@ ncmpi_inq_unlimdim(int ncid, int *xtendimp)
     status = ncmpii_NC_check_id(ncid, &ncp);
     if (status != NC_NOERR) return status;
 
+    /* TODO: it makes no sense xtendimp being NULL */
     if (xtendimp != NULL)
-        *xtendimp = ncmpii_find_NC_Udim(&ncp->dims, NULL);
+        /* *xtendimp = ncmpii_find_NC_Udim(&ncp->dims, NULL); */
+        *xtendimp = ncp->dims.unlimited_id;
 
     return NC_NOERR;
 }
diff --git a/src/lib/nc.h b/src/lib/nc.h
index a28945b..15cc48c 100644
--- a/src/lib/nc.h
+++ b/src/lib/nc.h
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: nc.h 2319 2016-02-04 08:04:01Z wkliao $ */
+/* $Id: nc.h 2588 2016-10-30 04:14:15Z wkliao $ */
 #ifndef _NC_H_
 #define _NC_H_
 
@@ -70,7 +70,7 @@ enum API_KIND {
 #endif
 
 /* ncmpi_create/ncmpi_open set up header to be 'chunksize' big and to grow
- * by 'chunksize' as new items adde. This used to be 4k. 256k lets us read
+ * by 'chunksize' as new items added. This used to be 4k. 256k lets us read
  * in an entire climate header in one go */
 #define NC_DEFAULT_CHUNKSIZE 262144
 
@@ -115,9 +115,9 @@ typedef enum {
     NC_UNSPECIFIED =  0,
 /*  NC_BITFIELD    =  7, */
 /*  NC_STRING      =  8, */
-    NC_DIMENSION   = 10,
-    NC_VARIABLE    = 11,
-    NC_ATTRIBUTE   = 12
+    NC_DIMENSION   = 10,  /* \x00 \x00 \x00 \x0A */
+    NC_VARIABLE    = 11,  /* \x00 \x00 \x00 \x0B */
+    NC_ATTRIBUTE   = 12   /* \x00 \x00 \x00 \x0C */
 } NCtype;
 
 
@@ -165,14 +165,38 @@ typedef struct {
 #endif
 } NC_dim;
 
+#define NC_NAME_TABLE_CHUNK 16
+#define HASH_TABLE_SIZE 256
+/*
+#define HASH_FUNC(x) ncmpii_jenkins_one_at_a_time_hash(x)
+#define HASH_FUNC(x) ncmpii_additive_hash(x)
+#define HASH_FUNC(x) ncmpii_rotating_hash(x)
+#define HASH_FUNC(x) ncmpii_Pearson_hash(x)
+*/
+#define HASH_FUNC(x) ncmpii_Bernstein_hash(x)
+/* Look like Bernstein's hashing function performs the best */
+
+/* For the initial naive implementation of hashing:
+ * #define HASH_FUNC(x) (unsigned char)x[0]
+ * if used this simple hash function, HASH_TABLE_SIZE must be 256 which is the
+ * number of possible keys can be stored in an unsigned char
+ */
+
+typedef struct NC_nametable {
+    int  num;
+    int *list; /* variable IDs */
+} NC_nametable;
+
 /* the dimension ID returned from ncmpi_def_dim() is an integer pointer
  * which means the total number of defined dimension allowed in a file
  * is up to 2^31-1. Thus, the member ndefined below should be of type int.
  */
 typedef struct NC_dimarray {
-    int      nalloc;    /* number allocated >= ndefined */
-    int      ndefined;  /* number of defined dimensions */
-    NC_dim **value;
+    int            nalloc;    /* number allocated >= ndefined */
+    int            ndefined;  /* number of defined dimensions */
+    int            unlimited_id;  /* -1 for not defined, otherwise >= 0 */
+    NC_dim       **value;
+    NC_nametable   nameT[HASH_TABLE_SIZE]; /* table for quick name lookup */
 } NC_dimarray;
 
 /* Begin defined in dim.c */
@@ -203,23 +227,6 @@ ncmpii_dup_NC_dimarray(NC_dimarray *ncap, const NC_dimarray *ref);
 extern NC_dim *
 ncmpii_elem_NC_dimarray(const NC_dimarray *ncap, int elem);
 
-extern int
-ncmpi_def_dim(int ncid, const char *name, MPI_Offset size, int *dimidp);
-
-extern int
-ncmpi_rename_dim( int ncid, int dimid, const char *newname);
-
-extern int
-ncmpi_inq_dimid(int ncid, const char *name, int *dimid_ptr);
-
-extern int
-ncmpi_inq_dim(int ncid, int dimid, char *name, MPI_Offset *sizep);
-
-extern int
-ncmpi_inq_dimname(int ncid, int dimid, char *name);
-
-extern int
-ncmpi_inq_dimlen(int ncid, int dimid, MPI_Offset *lenp);
 /* End defined in dim.c */
 
 /*
@@ -271,84 +278,6 @@ ncmpii_dup_NC_attrarray(NC_attrarray *ncap, const NC_attrarray *ref);
 extern NC_attr *
 ncmpii_elem_NC_attrarray(const NC_attrarray *ncap, MPI_Offset elem);
 
-extern int
-ncmpi_put_att_text(int ncid, int varid, const char *name,
-        MPI_Offset nelems, const char *value);
-
-extern int
-ncmpi_get_att_text(int ncid, int varid, const char *name, char *str);
-
-extern int
-ncmpi_put_att_schar(int ncid, int varid, const char *name,
-        nc_type type, MPI_Offset nelems, const signed char *value);
-
-extern int
-ncmpi_get_att_schar(int ncid, int varid, const char *name, signed char *tp);
-
-extern int
-ncmpi_put_att_uchar(int ncid, int varid, const char *name,
-        nc_type type, MPI_Offset nelems, const unsigned char *value);
-
-extern int
-ncmpi_get_att_uchar(int ncid, int varid, const char *name, unsigned char *tp);
-
-extern int
-ncmpi_put_att_short(int ncid, int varid, const char *name,
-        nc_type type, MPI_Offset nelems, const short *value);
-
-extern int
-ncmpi_get_att_short(int ncid, int varid, const char *name, short *tp);
-
-extern int
-ncmpi_put_att_int(int ncid, int varid, const char *name,
-        nc_type type, MPI_Offset nelems, const int *value);
-
-extern int
-ncmpi_get_att_int(int ncid, int varid, const char *name, int *tp);
-
-extern int
-ncmpi_put_att_long(int ncid, int varid, const char *name,
-        nc_type type, MPI_Offset nelems, const long *value);
-
-extern int
-ncmpi_get_att_long(int ncid, int varid, const char *name, long *tp);
-
-extern int
-ncmpi_put_att_float(int ncid, int varid, const char *name,
-        nc_type type, MPI_Offset nelems, const float *value);
-extern int
-ncmpi_get_att_float(int ncid, int varid, const char *name, float *tp);
-extern int
-ncmpi_put_att_double(int ncid, int varid, const char *name,
-        nc_type type, MPI_Offset nelems, const double *value);
-extern int
-ncmpi_get_att_double(int ncid, int varid, const char *name, double *tp);
-
-extern int
-ncmpi_inq_attid(int ncid, int varid, const char *name, int *attnump);
-
-extern int
-ncmpi_inq_atttype(int ncid, int varid, const char *name, nc_type *datatypep);
-
-extern int
-ncmpi_inq_attlen(int ncid, int varid, const char *name, MPI_Offset *lenp);
-
-extern int
-ncmpi_inq_att(int ncid, int varid, const char *name,
-        nc_type *datatypep, MPI_Offset *lenp);
-
-extern int
-ncmpi_copy_att(int ncid_in, int varid_in, const char *name,
-        int ncid_out, int ovarid);
-
-extern int
-ncmpi_rename_att( int ncid, int varid, const char *name, const char *newname);
-
-extern int
-ncmpi_del_att(int ncid, int varid, const char *name);
-
-extern int
-ncmpi_inq_attname(int ncid, int varid, int attnum, char *name);
 /* End defined in attr.c */
 
 /*
@@ -377,10 +306,11 @@ typedef struct {
 
 /* note: we only allow less than 2^31-1 variables defined in a file */
 typedef struct NC_vararray {
-    int      nalloc;      /* number allocated >= ndefined */
-    int      ndefined;    /* number of defined variables */
-    int      num_rec_vars;/* number of defined record variables */
-    NC_var **value;
+    int            nalloc;      /* number allocated >= ndefined */
+    int            ndefined;    /* number of defined variables */
+    int            num_rec_vars;/* number of defined record variables */
+    NC_var       **value;
+    NC_nametable   nameT[HASH_TABLE_SIZE]; /* table for quick name lookup */
 } NC_vararray;
 
 /* Begin defined in var.c */
@@ -406,7 +336,7 @@ extern int
 ncmpii_dup_NC_vararray(NC_vararray *ncap, const NC_vararray *ref);
 
 extern int
-ncmpii_NC_var_shape64(NC *ncp, NC_var *varp, const NC_dimarray *dims);
+ncmpii_NC_var_shape64(NC_var *varp, const NC_dimarray *dims);
 
 extern int
 ncmpii_NC_check_vlen(NC_var *varp, MPI_Offset vlen_max);
@@ -414,37 +344,6 @@ ncmpii_NC_check_vlen(NC_var *varp, MPI_Offset vlen_max);
 extern int
 ncmpii_NC_lookupvar(NC *ncp, int varid, NC_var **varp);
 
-extern int
-ncmpi_def_var(int ncid, const char *name, nc_type type,
-        int ndims, const int *dimidsp, int *varidp);
-
-extern int
-ncmpi_rename_var(int ncid, int varid, const char *newname);
-
-extern int
-ncmpi_inq_var(int ncid, int varid, char *name, nc_type *typep,
-        int *ndimsp, int *dimids, int *nattsp);
-
-extern int
-ncmpi_inq_varid(int ncid, const char *name, int *varid_ptr);
-
-extern int
-ncmpi_inq_varname(int ncid, int varid, char *name);
-
-extern int
-ncmpi_inq_vartype(int ncid, int varid, nc_type *typep);
-
-extern int
-ncmpi_inq_varndims(int ncid, int varid, int *ndimsp);
-
-extern int
-ncmpi_inq_vardimid(int ncid, int varid, int *dimids);
-
-extern int
-ncmpi_inq_varnatts(int ncid, int varid, int *nattsp);
-
-extern int
-ncmpi_rename_var(int ncid, int varid, const char *newname);
 /* End defined in var.c */
 
 #define IS_RECVAR(vp) \
@@ -454,11 +353,12 @@ ncmpi_rename_var(int ncid, int varid, const char *newname);
  *  The PnetCDF non-blocking I/O request type
  */
 typedef struct NC_req {
-    int            id;
-    int            rw_flag;
+    int            id;          /* even number for write, odd for read */
     void          *buf;         /* the original user buffer */
     void          *xbuf;        /* the buffer used to read/write, may point to
                                    the same address as buf */
+    MPI_Offset     num_recs;    /* number of records requested (1 for
+                                   fixed-size variable) */
     int            buftype_is_contig;
     int            need_swap_back_buf;
     int            abuf_index;  /* index in the abuf occupy_table
@@ -481,9 +381,6 @@ typedef struct NC_req {
     MPI_Datatype   ptype;        /* element data type in buftype */
     MPI_Datatype   imaptype;     /* derived data type constructed from imap */
     int           *status;       /* pointer to user's status */
-    int            num_subreqs;  /* each record is a subrequest */
-    struct NC_req *subreqs;      /* [num_subreq] */
-    struct NC_req *next;
 } NC_req;
 
 #define NC_ABUF_DEFAULT_TABLE_SIZE 128
@@ -503,6 +400,9 @@ typedef struct NC_buf {
     void          *buf;
 } NC_buf;
 
+/* chunk size for allocating read/write nonblocking request lists */
+#define NC_REQUEST_CHUNK 1024
+
 struct NC {
     /* linked list of currently opened netcdf files */
     struct NC *next;
@@ -515,13 +415,14 @@ struct NC {
     struct NC *old;
     /* flags */
 #define NC_INDEP  0x10000   /* in independent data mode, cleared by endindep */
-#define NC_CREAT  0x20000   /* in create phase, cleared by ncenddef */
-#define NC_INDEF  0x80000   /* in define mode, cleared by ncenddef */
+#define NC_CREAT  0x20000   /* in create phase, cleared by enddef */
+#define NC_INDEF  0x80000   /* in define mode, cleared by enddef */
 #define NC_NSYNC  0x100000  /* synchronise numrecs on change */
 #define NC_HSYNC  0x200000  /* synchronise whole header on change */
 #define NC_NDIRTY 0x400000  /* numrecs has changed */
 #define NC_HDIRTY 0x800000  /* header info has changed */
 /* NC_NOFILL is defined in netcdf.h, historical interface */
+    int           format;   /* 1, 2, or 5 corresponding to CDF-1, 2, or 5 */
     int           flags;
     int           safe_mode;    /* 0 or 1, for parameter consistency check */
     int           subfile_mode; /* 0 or 1, for disable/enable subfiling */
@@ -535,14 +436,14 @@ struct NC {
     MPI_Offset    recsize;  /* length of 'record': sum of single record sizes
                                of all the record variables */
     MPI_Offset    numrecs;  /* number of 'records' allocated */
-    int           numGetReqs;  /* number of pending nonblocking get requests */
-    int           numPutReqs;  /* number of pending nonblocking put requests */
     NC_dimarray   dims;     /* dimensions defined */
     NC_attrarray  attrs;    /* global attributes defined */
     NC_vararray   vars;     /* variables defined */
-    NC_req       *head;     /* linked list head of nonblocking requests */
-    NC_req       *tail;     /* tail of the linked list */
-    NC_buf       *abuf;     /* attached buffer, used by bput APIs */
+    int           numGetReqs;  /* number of pending nonblocking get requests */
+    int           numPutReqs;  /* number of pending nonblocking put requests */
+    NC_req       *get_list;    /* list of nonblocking read requests */
+    NC_req       *put_list;    /* list of nonblocking write requests */
+    NC_buf       *abuf;        /* attached buffer, used by bput APIs */
 };
 
 #define NC_readonly(ncp) \
@@ -645,30 +546,6 @@ ncmpii__enddef(NC *ncp, MPI_Offset h_minfree, MPI_Offset v_align,
 extern int
 ncmpii_close(NC *ncp);
 
-extern int
-ncmpi_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *xtendimp);
-
-extern int
-ncmpi_inq_ndims(int ncid, int *ndimsp);
-
-extern int
-ncmpi_inq_nvars(int ncid, int *nvarsp);
-
-extern int
-ncmpi_inq_natts(int ncid, int *nattsp);
-
-extern int
-ncmpi_inq_unlimdim(int ncid, int *xtendimp);
-
-extern int
-ncmpi_get_default_format(void);
-
-extern int
-ncmpi_inq_num_rec_vars(int ncid, int *nump);
-
-extern int
-ncmpi_inq_num_fix_vars(int ncid, int *nump);
-
 /* End defined in nc.c */
 
 #if 0
@@ -712,8 +589,6 @@ typedef struct bufferinfo {
     void       *pos;      /* current position in buffer */
     MPI_Offset  size;     /* size of the buffer */
     MPI_Offset  index;    /* index of current position in buffer */
-    MPI_Offset  put_size; /* amount of writes so far in bytes */
-    MPI_Offset  get_size; /* amount of reads  so far in bytes */
 } bufferinfo;
 
 extern int
@@ -767,7 +642,6 @@ NC_computeshapes(NC *ncp);
 /* end defined in mpincio.h */
 
 /* begin defined in error.c */
-const char* ncmpi_strerror(int err);
 
 int ncmpii_handle_error(int mpi_errorcode, char *msg);
 
@@ -780,52 +654,59 @@ int ncmpii_handle_error(int mpi_errorcode, char *msg);
  * ../nc_test/tests.h if you change these.
  */
 
-int ncmpii_x_putn_schar (void *xbuf, const void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_putn_uchar (void *xbuf, const void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_putn_short (void *xbuf, const void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_putn_ushort(void *xbuf, const void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_putn_int   (void *xbuf, const void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_putn_uint  (void *xbuf, const void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_putn_float (void *xbuf, const void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_putn_double(void *xbuf, const void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_putn_int64 (void *xbuf, const void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_putn_uint64(void *xbuf, const void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_getn_schar (const void *xbuf, void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_getn_uchar (const void *xbuf, void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_getn_short (const void *xbuf, void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_getn_ushort(const void *xbuf, void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_getn_int   (const void *xbuf, void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_getn_uint  (const void *xbuf, void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_getn_float (const void *xbuf, void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_getn_double(const void *xbuf, void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_getn_int64 (const void *xbuf, void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
-int ncmpii_x_getn_uint64(const void *xbuf, void *buf, MPI_Offset nelems,
-                        MPI_Datatype datatype);
+int ncmpii_x_putn_NC_CHAR  (void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_putn_NC_BYTE  (int cdf_ver,
+                           void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype, void *fillp);
+int ncmpii_x_putn_NC_UBYTE (void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype, void *fillp);
+int ncmpii_x_putn_NC_SHORT (void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype, void *fillp);
+int ncmpii_x_putn_NC_USHORT(void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype, void *fillp);
+int ncmpii_x_putn_NC_INT   (void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype, void *fillp);
+int ncmpii_x_putn_NC_UINT  (void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype, void *fillp);
+int ncmpii_x_putn_NC_FLOAT (void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype, void *fillp);
+int ncmpii_x_putn_NC_DOUBLE(void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype, void *fillp);
+int ncmpii_x_putn_NC_INT64 (void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype, void *fillp);
+int ncmpii_x_putn_NC_UINT64(void *xbuf, const void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype, void *fillp);
+
+int ncmpii_x_getn_NC_CHAR  (const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_getn_NC_BYTE  (int cdf_ver,
+                           const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_getn_NC_UBYTE (const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_getn_NC_SHORT (const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_getn_NC_USHORT(const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_getn_NC_INT   (const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_getn_NC_UINT  (const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_getn_NC_FLOAT (const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_getn_NC_DOUBLE(const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_getn_NC_INT64 (const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
+int ncmpii_x_getn_NC_UINT64(const void *xbuf, void *buf, MPI_Offset nelems,
+                           MPI_Datatype datatype);
 
 int NC_start_count_stride_ck(const NC *ncp, const NC_var *varp,
                 const MPI_Offset *start, const MPI_Offset *count,
                 const MPI_Offset *stride, const int rw_flag);
 
-int ncmpii_need_convert(nc_type nctype,MPI_Datatype mpitype);
+int ncmpii_need_convert(int format, nc_type nctype, MPI_Datatype mpitype);
 
 int ncmpii_need_swap(nc_type nctype,MPI_Datatype mpitype);
 
@@ -842,6 +723,8 @@ int ncmpii_get_offset(NC *ncp, NC_var *varp, const MPI_Offset starts[],
 
 int ncmpii_check_mpifh(NC* ncp, int collective);
 
+int ncmpii_write_numrecs(NC *ncp, MPI_Offset new_numrecs);
+
 int ncmpii_sync_numrecs(NC *ncp, MPI_Offset newnumrecs);
 
 int ncmpii_vars_create_filetype(NC* ncp, NC_var* varp,
@@ -899,12 +782,8 @@ ncmpii_inq_files_opened(int *num, int *ncids);
 extern MPI_Datatype
 ncmpii_nc2mpitype(nc_type type);
 
-extern int
-ncmpii_set_iget_callback(NC *ncp, int reqid, void *tmpBuf, void *userBuf,
-                         int userBufCount, MPI_Datatype userBufType);
-
-extern int
-ncmpii_set_iput_callback(NC *ncp, int reqid, void *tmpPutBuf);
+extern nc_type
+ncmpii_mpi2nctype(MPI_Datatype itype);
 
 extern int
 ncmpii_end_indep_data(NC *ncp); 
@@ -932,10 +811,36 @@ ncmpii_fill_vars(NC *ncp);
 extern int
 ncmpii_sanity_check(int ncid, int varid, const MPI_Offset *start,
                     const MPI_Offset *count, MPI_Offset bufcount,
-                    enum API_KIND api, int mustInDataMode, int isFlexAPI,
+                    MPI_Datatype buftype, enum API_KIND api,
+                    int isFlexibleAPI, int mustInDataMode,
                     int rw_flag, int io_method, NC **ncp, NC_var **varp);
 
 extern char*
 ncmpii_err_code_name(int err);
 
+extern int
+ncmpii_jenkins_one_at_a_time_hash(const char *str_name);
+
+extern int
+ncmpii_additive_hash(const char *str_name);
+
+extern int
+ncmpii_rotating_hash(const char *str_name);
+
+extern int
+ncmpii_Bernstein_hash(const char *str_name);
+
+extern int
+ncmpii_Pearson_hash(const char *str_name);
+
+extern int
+ncmpii_update_name_lookup_table(NC_nametable *nameT, const int id,
+                                const char *oldname, const char *newname);
+
+extern int
+ncmpii_inq_var_fill(NC_var *varp, void *fill_value);
+
+extern int
+ncmpii_inq_default_fill_value(int type, void *fill_value);
+
 #endif /* _NC_H_ */
diff --git a/src/lib/ncconfig.h.in b/src/lib/ncconfig.h.in
index 0fdb044..e8856ad 100644
--- a/src/lib/ncconfig.h.in
+++ b/src/lib/ncconfig.h.in
@@ -3,9 +3,6 @@
 /* Define if building universal (internal helper macro) */
 #undef AC_APPLE_UNIVERSAL_BUILD
 
-/* configure command-line arguments used */
-#undef CONFIGURE_ARGS_CLEAN
-
 /* Define if to disable MPI_File_sync */
 #undef DISABLE_FILE_SYNC
 
@@ -358,29 +355,11 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
-/* Define if to enable debugging */
-#undef PNC_DEBUG
-
 /* Define if to enable malloc tracing */
 #undef PNC_MALLOC_TRACE
 
-/* PnetCDF release date string */
-#undef PNETCDF_RELEASE_DATE
-
-/* full PnetCDF version string */
-#undef PNETCDF_VERSION
-
-/* major version number */
-#undef PNETCDF_VERSION_MAJOR
-
-/* minor version number */
-#undef PNETCDF_VERSION_MINOR
-
-/* pre-release string */
-#undef PNETCDF_VERSION_PRE
-
-/* sub version number */
-#undef PNETCDF_VERSION_SUB
+/* Define if relaxed coord check is enabled */
+#undef RELAX_COORD_BOUND
 
 /* The size of `double', as computed by sizeof. */
 #undef SIZEOF_DOUBLE
@@ -436,6 +415,9 @@
 /* The size of `unsigned short', as computed by sizeof. */
 #undef SIZEOF_UNSIGNED_SHORT
 
+/* The size of `unsigned short int', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_SHORT_INT
+
 /* The size of `ushort', as computed by sizeof. */
 #undef SIZEOF_USHORT
 
diff --git a/src/lib/ncmpidtype.c b/src/lib/ncmpidtype.c
index fb5561a..a4f5ffa 100644
--- a/src/lib/ncmpidtype.c
+++ b/src/lib/ncmpidtype.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: ncmpidtype.c 2322 2016-02-26 22:47:06Z wkliao $ */
+/* $Id: ncmpidtype.c 2588 2016-10-30 04:14:15Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #ifdef HAVE_STDLIB_H
@@ -70,23 +70,30 @@ static MPI_Datatype ncmpii_type_filter(MPI_Datatype type)
 
     /* 4-byte integer types */
   {
-    MPI_Datatype int_4byte, uint_4byte;
+    MPI_Datatype int_4byte;
+#if (SIZEOF_LONG == 4)
+    MPI_Datatype uint_4byte;
+#endif
 #if (SIZEOF_INT == 4)
      int_4byte = MPI_INT;
+#if (SIZEOF_LONG == 4)
     uint_4byte = MPI_UNSIGNED;
+#endif
 #elif (SIZEOF_SHORT == 4)
      int_4byte = MPI_SHORT;
+#if (SIZEOF_LONG == 4)
     uint_4byte = MPI_UNSIGNED_SHORT;
+#endif
 #else
      int_4byte = MPI_DATATYPE_NULL; /* no 4-byte type? */
+#if (SIZEOF_LONG == 4)
     uint_4byte = MPI_DATATYPE_NULL;
 #endif
+#endif
 
 #ifdef HAVE_MPI_INTEGER
     if (type == MPI_INTEGER)
         return int_4byte;
-    if (type == MPI_UNSIGNED)
-        return uint_4byte;
 #endif
 #ifdef HAVE_MPI_INTEGER4
     if (type == MPI_INTEGER4)
@@ -349,9 +356,9 @@ int ncmpii_dtype_decode(MPI_Datatype dtype,
     return NC_NOERR;
   }
 
-  array_of_ints = (int *) NCI_Malloc(num_ints * SIZEOF_INT);
-  array_of_adds = (MPI_Aint *) NCI_Malloc(num_adds * SIZEOF_MPI_AINT);
-  array_of_dtypes = (MPI_Datatype *) NCI_Malloc(num_dtypes * sizeof(MPI_Datatype));
+  array_of_ints = (int *) NCI_Malloc((size_t)num_ints * SIZEOF_INT);
+  array_of_adds = (MPI_Aint *) NCI_Malloc((size_t)num_adds * SIZEOF_MPI_AINT);
+  array_of_dtypes = (MPI_Datatype *) NCI_Malloc((size_t)num_dtypes * sizeof(MPI_Datatype));
 
   MPI_Type_get_contents(dtype, num_ints, num_adds, num_dtypes,
                         array_of_ints, array_of_adds, array_of_dtypes);
diff --git a/src/lib/ncx.h b/src/lib/ncx.h
deleted file mode 100644
index 053507e..0000000
--- a/src/lib/ncx.h
+++ /dev/null
@@ -1,979 +0,0 @@
-/*
- *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
- *  See COPYRIGHT notice in top-level directory.
- */
-/* "$Id: ncx.h 2301 2016-01-10 19:21:33Z wkliao $" */
-
-#ifndef _NCX_H_
-#define _NCX_H_
-
-#include <mpi.h>
-
-#include "nc.h"
-#include "ncio.h"
-#include "fbits.h"
-#include "nctypes.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 "rnd.h"
-#include <stddef.h> /* size_t */
-#include <errno.h>
-#include <sys/types.h> /* off_t */
-
-
-#if defined(_CRAY) && !defined(_CRAYIEEE) && !defined(__crayx1)
-#define CRAYFLOAT 1 /* CRAY Floating point */
-#elif defined(_SX) && defined(_FLOAT2)	/* NEC SUPER-UX in CRAY mode */
-#define CRAYFLOAT 1 /* CRAY Floating point */
-#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
-
-/* additional data types in CDF-5 */
-#define X_SIZEOF_UBYTE		1
-#define X_SIZEOF_USHORT		2
-#define X_SIZEOF_UINT		4
-#define X_SIZEOF_LONGLONG	8
-#define X_SIZEOF_ULONGLONG	8
-#define X_SIZEOF_INT64		8
-#define X_SIZEOF_UINT64		8
-
-/*
- * For now, netcdf is limited to 32 bit sizes,
- * If compiled with support for "large files", then
- * netcdf will use a 64 bit off_t and it can then write a file
- * using 64 bit offsets.
- *  see also X_SIZE_MAX, X_OFF_MAX below
- */
-/* #define X_SIZEOF_OFF_T		(sizeof(off_t)) */
-#define X_SIZEOF_OFF_T		SIZEOF_OFF_T
-#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
-#define X_LONGLONG_MIN	(-9223372036854775807LL-1LL)
-#define X_LONGLONG_MAX	9223372036854775807LL
-#define X_ULONGLONG_MAX	18446744073709551615ULL
-#define X_FLOAT_MAX	3.402823466e+38f
-#define X_FLOAT_MIN	(-X_FLOAT_MAX)
-#define X_FLT_MAX	X_FLOAT_MAX	/* alias compatible with limits.h */
-#if defined(CRAYFLOAT) && CRAYFLOAT != 0
-/* 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_UINT_MAX
-#define X_OFF_MAX	X_INT_MAX
-
-
-/* Begin ncmpix_len */
-
-/*
- * ncmpix_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 ncmpix_len_char(nelems) \
-	_RNDUP((nelems), X_ALIGN)
-
-#define ncmpix_len_short(nelems) \
-	(((nelems) + (nelems)%2)  * X_SIZEOF_SHORT)
-
-#define ncmpix_len_int(nelems) \
-	((nelems) * X_SIZEOF_INT)
-
-#define ncmpix_len_long(nelems) \
-	((nelems) * X_SIZEOF_LONG)
-
-#define ncmpix_len_float(nelems) \
-	((nelems) * X_SIZEOF_FLOAT)
-
-#define ncmpix_len_double(nelems) \
-	((nelems) * X_SIZEOF_DOUBLE)
-
-#define ncmpix_len_ubyte(nelems) \
-	_RNDUP((nelems), X_ALIGN)
-
-#define ncmpix_len_ushort(nelems) \
-	(((nelems) + (nelems)%2)  * X_SIZEOF_USHORT)
-
-#define ncmpix_len_uint(nelems) \
-	((nelems) * X_SIZEOF_UINT)
-
-#define ncmpix_len_int64(nelems) \
-	((nelems) * X_SIZEOF_INT64)
-
-#define ncmpix_len_uint64(nelems) \
-	((nelems) * X_SIZEOF_UINT64)
-
-/* End ncmpix_len */
-
-#if defined(__CHAR_UNSIGNED__) && __CHAR_UNSIGNED__ != 0
-	/* '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 ncmpix_get_{external_type}_{internal_type}(
- *		const void *xp,
- *		internal_type *ip
- *	);
- *	int ncmpix_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 ncmpix 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 NC_NOERR 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.
- *
- */
-
-/*
- * Other primitive conversion functions
- * N.B. slightly different interface
- * Used by netcdf.
- */
-
-/* ncmpix_get_int_size_t */
-extern int
-ncmpix_get_size_t(const void **xpp, size_t *ulp);
-/* ncmpix_get_int_off_t */
-extern int
-ncmpix_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t);
-
-/* ncmpix_put_int_size_t */
-extern int
-ncmpix_put_size_t(void **xpp, const size_t *ulp);
-/* ncmpix_put_int_off_t */
-extern int
-ncmpix_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t);
-
-extern int
-ncmpix_get_uint32(const void **xpp, unsigned int *ip);
-extern int
-ncmpix_get_uint64(const void **xpp, unsigned long long *ip);
-extern int
-ncmpix_put_uint32(void **xpp, const unsigned int ip);
-extern int
-ncmpix_put_uint64(void **xpp, const unsigned long long ip);
-
-
-/*
- * 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 ncmpix_getn_{external_type}_{internal_type}(
- *		const void *xpp,
- *		size_t nelems,
- *		internal_type *ip
- *	);
- *	int ncmpix_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.
- *
- */
-
-/*---- schar ----------------------------------------------------------------*/
-extern int
-ncmpix_getn_schar_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_getn_schar_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_getn_schar_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_getn_schar_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_getn_schar_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_getn_schar_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_getn_schar_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_schar_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_getn_schar_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_getn_schar_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_getn_schar_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_pad_getn_schar_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_pad_getn_schar_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_pad_getn_schar_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_pad_getn_schar_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_pad_getn_schar_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_pad_getn_schar_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_pad_getn_schar_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_pad_getn_schar_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_pad_getn_schar_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_pad_getn_schar_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_pad_getn_schar_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_putn_schar_schar (void **xpp, MPI_Offset nelems, const schar   *ip);
-extern int
-ncmpix_putn_schar_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_putn_schar_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_putn_schar_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_putn_schar_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_putn_schar_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_putn_schar_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_schar_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_putn_schar_double(void **xpp, MPI_Offset nelems, const double  *ip);
-extern int
-ncmpix_putn_schar_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_putn_schar_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-extern int
-ncmpix_pad_putn_schar_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_pad_putn_schar_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_pad_putn_schar_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_pad_putn_schar_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_pad_putn_schar_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_pad_putn_schar_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_pad_putn_schar_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_pad_putn_schar_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_pad_putn_schar_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_pad_putn_schar_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_pad_putn_schar_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-/*---- uchar ----------------------------------------------------------------*/
-extern int
-ncmpix_getn_uchar_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_getn_uchar_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_getn_uchar_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_getn_uchar_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_getn_uchar_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_getn_uchar_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_getn_uchar_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_uchar_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_getn_uchar_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_getn_uchar_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_getn_uchar_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_pad_getn_uchar_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_pad_getn_uchar_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_pad_getn_uchar_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_pad_getn_uchar_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_pad_getn_uchar_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_pad_getn_uchar_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_pad_getn_uchar_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_pad_getn_uchar_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_pad_getn_uchar_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_pad_getn_uchar_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_pad_getn_uchar_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_putn_uchar_schar (void **xpp, MPI_Offset nelems, const schar   *ip);
-extern int
-ncmpix_putn_uchar_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_putn_uchar_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_putn_uchar_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_putn_uchar_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_putn_uchar_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_putn_uchar_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_uchar_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_putn_uchar_double(void **xpp, MPI_Offset nelems, const double  *ip);
-extern int
-ncmpix_putn_uchar_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_putn_uchar_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-extern int
-ncmpix_pad_putn_uchar_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_pad_putn_uchar_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_pad_putn_uchar_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_pad_putn_uchar_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_pad_putn_uchar_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_pad_putn_uchar_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_pad_putn_uchar_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_pad_putn_uchar_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_pad_putn_uchar_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_pad_putn_uchar_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_pad_putn_uchar_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-/*---- short ----------------------------------------------------------------*/
-extern int
-ncmpix_getn_short_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_getn_short_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_getn_short_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_getn_short_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_getn_short_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_getn_short_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_getn_short_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_short_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_getn_short_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_getn_short_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_getn_short_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_pad_getn_short_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_pad_getn_short_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_pad_getn_short_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_pad_getn_short_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_pad_getn_short_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_pad_getn_short_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_pad_getn_short_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_pad_getn_short_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_pad_getn_short_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_pad_getn_short_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_pad_getn_short_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_putn_short_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_putn_short_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_putn_short_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_putn_short_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_putn_short_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_putn_short_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_putn_short_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_short_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_putn_short_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_putn_short_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_putn_short_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-extern int
-ncmpix_pad_putn_short_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_pad_putn_short_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_pad_putn_short_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_pad_putn_short_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_pad_putn_short_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_pad_putn_short_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_pad_putn_short_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_pad_putn_short_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_pad_putn_short_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_pad_putn_short_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_pad_putn_short_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-/*---- ushort ---------------------------------------------------------------*/
-extern int
-ncmpix_getn_ushort_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_getn_ushort_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_getn_ushort_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_getn_ushort_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_getn_ushort_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_getn_ushort_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_getn_ushort_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_ushort_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_getn_ushort_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_getn_ushort_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_getn_ushort_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_pad_getn_ushort_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_pad_getn_ushort_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_pad_getn_ushort_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_pad_getn_ushort_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_pad_getn_ushort_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_pad_getn_ushort_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_pad_getn_ushort_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_pad_getn_ushort_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_pad_getn_ushort_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_pad_getn_ushort_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_pad_getn_ushort_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_putn_ushort_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_putn_ushort_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_putn_ushort_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_putn_ushort_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_putn_ushort_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_putn_ushort_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_putn_ushort_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_ushort_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_putn_ushort_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_putn_ushort_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_putn_ushort_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-extern int
-ncmpix_pad_putn_ushort_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_pad_putn_ushort_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_pad_putn_ushort_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_pad_putn_ushort_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_pad_putn_ushort_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_pad_putn_ushort_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_pad_putn_ushort_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_pad_putn_ushort_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_pad_putn_ushort_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_pad_putn_ushort_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_pad_putn_ushort_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-/*---- int ------------------------------------------------------------------*/
-extern int
-ncmpix_getn_int_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_getn_int_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_getn_int_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_getn_int_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_getn_int_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_getn_int_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_getn_int_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_long_long (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_int_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_getn_int_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_getn_int_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_getn_int_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_putn_int_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_putn_int_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_putn_int_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_putn_int_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_putn_int_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_putn_int_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_putn_int_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_long_long (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_int_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_putn_int_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_putn_int_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_putn_int_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-/*---- uint -----------------------------------------------------------------*/
-extern int
-ncmpix_getn_uint_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_getn_uint_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_getn_uint_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_getn_uint_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_getn_uint_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_getn_uint_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_getn_uint_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_long_long (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_uint_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_getn_uint_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_getn_uint_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_getn_uint_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_putn_uint_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_putn_uint_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_putn_uint_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_putn_uint_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_putn_uint_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_putn_uint_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_putn_uint_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_long_long (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_uint_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_putn_uint_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_putn_uint_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_putn_uint_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-/*---- float ----------------------------------------------------------------*/
-extern int
-ncmpix_getn_float_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_getn_float_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_getn_float_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_getn_float_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
-extern int
-ncmpix_getn_float_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_getn_float_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_getn_float_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_float_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_getn_float_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_getn_float_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_getn_float_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_putn_float_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_putn_float_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_putn_float_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_putn_float_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_putn_float_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_putn_float_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_putn_float_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_float_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_putn_float_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_putn_float_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_putn_float_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-/*---- double ---------------------------------------------------------------*/
-extern int
-ncmpix_getn_double_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_getn_double_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_getn_double_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_getn_double_ushort(const void **xpp, MPI_Offset nelems, ushort  *ip);
-extern int
-ncmpix_getn_double_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_getn_double_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_getn_double_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_double_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_getn_double_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_getn_double_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_getn_double_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_putn_double_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_putn_double_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_putn_double_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_putn_double_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_putn_double_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_putn_double_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_putn_double_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_double_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_putn_double_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_putn_double_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_putn_double_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-/*---- int64 ----------------------------------------------------------------*/
-extern int
-ncmpix_getn_int64_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_getn_int64_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_getn_int64_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_getn_int64_ushort(const void **xpp, MPI_Offset nelems, ushort  *ip);
-extern int
-ncmpix_getn_int64_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_getn_int64_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_getn_int64_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_int64_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_getn_int64_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_getn_int64_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_getn_int64_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_putn_int64_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_putn_int64_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_putn_int64_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_putn_int64_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_putn_int64_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_putn_int64_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_putn_int64_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_int64_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_putn_int64_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_putn_int64_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_putn_int64_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-/*---- uint64 ---------------------------------------------------------------*/
-extern int
-ncmpix_getn_uint64_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
-extern int
-ncmpix_getn_uint64_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
-extern int
-ncmpix_getn_uint64_short (const void **xpp, MPI_Offset nelems, short  *ip);
-extern int
-ncmpix_getn_uint64_ushort(const void **xpp, MPI_Offset nelems, ushort  *ip);
-extern int
-ncmpix_getn_uint64_int   (const void **xpp, MPI_Offset nelems, int    *ip);
-extern int
-ncmpix_getn_uint64_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
-extern int
-ncmpix_getn_uint64_long  (const void **xpp, MPI_Offset nelems, long   *ip);
-extern int
-ncmpix_getn_uint64_float (const void **xpp, MPI_Offset nelems, float  *ip);
-extern int
-ncmpix_getn_uint64_double(const void **xpp, MPI_Offset nelems, double *ip);
-extern int
-ncmpix_getn_uint64_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
-extern int
-ncmpix_getn_uint64_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
-
-extern int
-ncmpix_putn_uint64_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
-extern int
-ncmpix_putn_uint64_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
-extern int
-ncmpix_putn_uint64_short (void **xpp, MPI_Offset nelems, const short  *ip);
-extern int
-ncmpix_putn_uint64_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
-extern int
-ncmpix_putn_uint64_int   (void **xpp, MPI_Offset nelems, const int    *ip);
-extern int
-ncmpix_putn_uint64_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
-extern int
-ncmpix_putn_uint64_long  (void **xpp, MPI_Offset nelems, const long   *ip);
-extern int
-ncmpix_putn_uint64_float (void **xpp, MPI_Offset nelems, const float  *ip);
-extern int
-ncmpix_putn_uint64_double(void **xpp, MPI_Offset nelems, const double *ip);
-extern int
-ncmpix_putn_uint64_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
-extern int
-ncmpix_putn_uint64_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
-
-
-/*
- * Other aggregate conversion functions.
- */
-
-/* read ASCII characters */
-extern int
-ncmpix_getn_text(const void **xpp, MPI_Offset nchars, char *cp);
-extern int
-ncmpix_pad_getn_text(const void **xpp, MPI_Offset nchars, char *cp);
-
-/* write ASCII characters */
-extern int
-ncmpix_putn_text(void **xpp, MPI_Offset nchars, const char *cp);
-extern int
-ncmpix_pad_putn_text(void **xpp, MPI_Offset nchars, const char *cp);
-
-/* for symmetry */
-#define ncmpix_getn_char_char(xpp, nelems, fillp) ncmpix_getn_text(xpp, nelems, fillp)
-#define ncmpix_putn_char_char(xpp, nelems, fillp) ncmpix_putn_text(xpp, nelems, fillp)
-
-/* read opaque data */
-extern int
-ncmpix_getn_void(const void **xpp, MPI_Offset nchars, void *vp);
-extern int
-ncmpix_pad_getn_void(const void **xpp, MPI_Offset nchars, void *vp);
-
-/* write opaque data */
-extern int
-ncmpix_putn_void(void **xpp, MPI_Offset nchars, const void *vp);
-extern int
-ncmpix_pad_putn_void(void **xpp, MPI_Offset nchars, const void *vp);
-
-#endif /* _NCX_H_ */
diff --git a/src/lib/ncx.m4 b/src/lib/ncx.m4
index b7b7554..3d1cd75 100644
--- a/src/lib/ncx.m4
+++ b/src/lib/ncx.m4
@@ -1,5 +1,7 @@
 dnl Process this m4 file to produce 'C' language file.
 dnl
+dnl This file is supposed to be the same as PnetCDF's ncx.m4
+dnl
 dnl If you see this line, you can ignore the next one.
 /* Do not edit this file. It is produced from the corresponding .m4 source */
 dnl
@@ -7,15 +9,106 @@ dnl
  *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: ncx.m4 2299 2016-01-09 06:14:37Z wkliao $ */
+/* $Id: ncx.m4 2601 2016-11-07 04:54:42Z wkliao $ */
 
-#if HAVE_CONFIG_H
-# include "ncconfig.h"
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wunused-parameter"
 #endif
 
+dnl
+dnl If the m4 macro "ERANGE_FILL" is defined, the I/O to data elements
+dnl that cause NC_ERANGE will be filled with the NC default fill values.
+dnl
+
+define(`SKIP_LOOP', `ifdef(`ERANGE_FILL', `$1++; $2++; continue;')')
+
+dnl
+dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
+dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types
+dnl (MPI_Offset vs. size_t), and function name substrings for external data
+dnl types.
+dnl
+
+ifdef(`PNETCDF',`
+`#'if HAVE_CONFIG_H
+`#'include <ncconfig.h>
+`#'endif')
+
 #include <stdio.h>
 #include <stdlib.h>
-#include <mpi.h>
+#include <string.h>
+#include <limits.h>
+
+ifdef(`PNETCDF',`
+`#'include "ncx.h"
+`#'include "macro.h"',`
+`#'pragma GCC diagnostic ignored "-Wdeprecated"
+`#'include "ncx.h"
+`#'include "nc3dispatch.h"')
+
+define(`IntType',  `ifdef(`PNETCDF', `MPI_Offset', `size_t')')dnl
+define(`APIPrefix',`ifdef(`PNETCDF', `ncmpi', `nc')')dnl
+define(`NC_TYPE',  `ifdef(`PNETCDF', `ifelse(
+`$1', `schar',  `NC_BYTE',dnl
+`$1', `uchar',  `NC_UBYTE',dnl
+`$1', `short',  `NC_SHORT',dnl
+`$1', `ushort', `NC_USHORT',dnl
+`$1', `int',    `NC_INT',dnl
+`$1', `uint',   `NC_UINT',dnl
+`$1', `float',  `NC_FLOAT',dnl
+`$1', `double', `NC_DOUBLE',dnl
+`$1', `int64',  `NC_INT64',dnl
+`$1', `uint64', `NC_UINT64')',dnl
+`ifelse(
+`$1', `int64', `longlong',dnl
+`$1', `uint64', `ulonglong',dnl
+`$1')')')dnl
+
+ifdef(`PNETCDF',,`define(`DEBUG_RETURN_ERROR',`return $1;')')
+ifdef(`PNETCDF',,`define(`DEBUG_ASSIGN_ERROR',`$1 = $2;')')
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h> /* uint16_t, uint32_t, uint64_t */
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>   /* uint16_t, uint32_t, uint64_t */
+#endif
+
+dnl
+dnl *fillp is the fill value in internal representation
+dnl
+define(`FillValue', `ifdef(`ERANGE_FILL', `ifelse(
+`$1', `schar',     `if (fillp != NULL) memcpy($2, fillp, 1);',dnl
+`$1', `uchar',     `if (fillp != NULL) memcpy($2, fillp, 1);',dnl
+`$1', `short',     `if (fillp != NULL) memcpy($2, fillp, 2);',dnl
+`$1', `ushort',    `if (fillp != NULL) memcpy($2, fillp, 2);',dnl
+`$1', `int',       `if (fillp != NULL) memcpy($2, fillp, 4);',dnl
+`$1', `uint',      `if (fillp != NULL) memcpy($2, fillp, 4);',dnl
+`$1', `long',      `if (fillp != NULL) memcpy($2, fillp, SIZEOF_LONG);', dnl
+`$1', `ulong',     `if (fillp != NULL) memcpy($2, fillp, SIZEOF_ULONG);',dnl
+`$1', `float',     `if (fillp != NULL) memcpy($2, fillp, 4);',dnl
+`$1', `double',    `if (fillp != NULL) memcpy($2, fillp, 8);',dnl
+`$1', `longlong',  `if (fillp != NULL) memcpy($2, fillp, 8);',dnl
+`$1', `int64',     `if (fillp != NULL) memcpy($2, fillp, 8);',dnl
+`$1', `ulonglong', `if (fillp != NULL) memcpy($2, fillp, 8);',dnl
+`$1', `uint64',    `if (fillp != NULL) memcpy($2, fillp, 8);')')')dnl
+
+dnl
+dnl
+define(`FillDefaultValue', `ifelse(
+`$1', `schar',     `NC_FILL_BYTE',
+`$1', `uchar',     `NC_FILL_UBYTE',
+`$1', `short',     `NC_FILL_SHORT',
+`$1', `ushort',    `NC_FILL_USHORT',
+`$1', `int',       `NC_FILL_INT',
+`$1', `uint',      `NC_FILL_UINT',
+`$1', `long',      `NC_FILL_INT',
+`$1', `ulong',     `NC_FILL_UINT',
+`$1', `float',     `NC_FILL_FLOAT',
+`$1', `double',    `NC_FILL_DOUBLE',
+`$1', `longlong',  `NC_FILL_INT64',
+`$1', `int64',     `NC_FILL_INT64',
+`$1', `ulonglong', `NC_FILL_UINT64',
+`$1', `uint64',    `NC_FILL_UINT64')')dnl
 
 /*
  * The only error code returned from subroutines in this file is NC_ERANGE,
@@ -26,12 +119,6 @@ dnl
  * An external data representation interface.
  */
 
-#include <string.h>
-#include <limits.h>
-#include "ncx.h"
-#include "nc.h"
-#include "macro.h"
-
 /* alias poorly named limits.h macros */
 #define  SHORT_MAX  SHRT_MAX
 #define  SHORT_MIN  SHRT_MIN
@@ -80,19 +167,65 @@ dnl
 #define Max(a,b) ((a) > (b) ? (a) : (b))
 
 #ifndef SIZEOF_UCHAR
+#ifdef  SIZEOF_UNSIGNED_CHAR
 #define SIZEOF_UCHAR SIZEOF_UNSIGNED_CHAR
+#else
+#error "unknown SIZEOF_UCHAR"
 #endif
+#endif
+
 #ifndef SIZEOF_USHORT
+#ifdef  SIZEOF_UNSIGNED_SHORT_INT
 #define SIZEOF_USHORT SIZEOF_UNSIGNED_SHORT_INT
+#elif defined(SIZEOF_UNSIGNED_SHORT)
+#define SIZEOF_USHORT SIZEOF_UNSIGNED_SHORT
+#else
+#error "unknown SIZEOF_USHORT"
+#endif
 #endif
+
 #ifndef SIZEOF_UINT
+#ifdef  SIZEOF_UNSIGNED_INT
 #define SIZEOF_UINT SIZEOF_UNSIGNED_INT
+#else
+#error "unknown SIZEOF_UINT"
+#endif
 #endif
+
 #ifndef SIZEOF_LONGLONG
+#ifdef  SIZEOF_LONG_LONG
 #define SIZEOF_LONGLONG SIZEOF_LONG_LONG
+#else
+#error "unknown SIZEOF_LONGLONG"
 #endif
+#endif
+
+#ifndef SIZEOF_INT64
+#ifdef  SIZEOF_LONG_LONG
+#define SIZEOF_INT64 SIZEOF_LONG_LONG
+#elif defined(SIZEOF_LONGLONG)
+#define SIZEOF_INT64 SIZEOF_LONGLONG
+#else
+#error "unknown SIZEOF_INT64"
+#endif
+#endif
+
 #ifndef SIZEOF_ULONGLONG
+#ifdef  SIZEOF_UNSIGNED_LONG_LONG
 #define SIZEOF_ULONGLONG SIZEOF_UNSIGNED_LONG_LONG
+#else
+#error "unknown SIZEOF_ULONGLONG"
+#endif
+#endif
+
+#ifndef SIZEOF_UINT64
+#ifdef  SIZEOF_UNSIGNED_LONG_LONG
+#define SIZEOF_UINT64 SIZEOF_UNSIGNED_LONG_LONG
+#elif defined(SIZEOF_ULONGLONG)
+#define SIZEOF_UINT64 SIZEOF_ULONGLONG
+#else
+#error "unknown SIZEOF_UINT64"
+#endif
 #endif
 
 /*
@@ -138,17 +271,35 @@ static const char nada[X_ALIGN] = {0, 0, 0, 0};
  */
 
 #define SWAP2(a) ( (((a) & 0xff) << 8) | \
-		(((a) >> 8) & 0xff) )
+                   (((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, MPI_Offset nn)
-{
+                  (((a) <<  8) & 0x00ff0000) | \
+                  (((a) >>  8) & 0x0000ff00) | \
+                  (((a) >> 24) & 0x000000ff) )
+
+#define SWAP8(a) ( (((a) & 0x00000000000000FFULL) << 56) | \
+                   (((a) & 0x000000000000FF00ULL) << 40) | \
+                   (((a) & 0x0000000000FF0000ULL) << 24) | \
+                   (((a) & 0x00000000FF000000ULL) <<  8) | \
+                   (((a) & 0x000000FF00000000ULL) >>  8) | \
+                   (((a) & 0x0000FF0000000000ULL) >> 24) | \
+                   (((a) & 0x00FF000000000000ULL) >> 40) | \
+                   (((a) & 0xFF00000000000000ULL) >> 56) )
+
+
+inline static void
+swapn2b(void *dst, const void *src, IntType nn)
+{
+    /* it is OK if dst == src */
+    int i;
+    uint16_t *op = (uint16_t*) dst;
+    uint16_t *ip = (uint16_t*) src;
+    for (i=0; i<nn; i++) {
+        op[i] = ip[i];
+        op[i] = (uint16_t)SWAP2(op[i]);
+    }
+#if 0
 	char *op = dst;
 	const char *ip = src;
 
@@ -177,36 +328,68 @@ swapn2b(void *dst, const void *src, MPI_Offset nn)
 		*op++ = *(++ip);
 		*op++ = *(ip++ -1);
 	}
+#endif
 }
 
 # ifndef vax
-static void
+inline 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];
-
-/* We can use bitwise operations as below.
-   Here, unsigned int must be of size 4 bytes.
+    /* copy over, make the below swap in-place */
+    uint32_t tmp = *(uint32_t*)src;
+    tmp = SWAP4(tmp);
+    memcpy(dst, &tmp, 4);
+
+    /* Codes below will cause "break strict-aliasing rules" in gcc
+    uint32_t *op = (uint32_t*)dst;
+    *op = *(uint32_t*)src;
+    *op = SWAP4(*op);
+    */
+
+    /* Below are copied from netCDF-4.
+     * See https://bugtracking.unidata.ucar.edu/browse/NCF-338
+     * Quote "One issue we are wrestling with is how compilers optimize this
+     * code.  For some reason, we are actually needing to add an artificial
+     * move to a 4 byte space to get it to work.  I think what is happening is
+     * that the optimizer is bit shifting within a double, which is incorrect.
+     * The following code actually does work correctly.
+     *  This is in Linux land, gcc.
+     *
+     * However, the above in-place byte-swap does not appear affected by this.
+     */
+#if 0
+    uint32_t *ip = (uint32_t*)src;
+    uint32_t tempOut;  /* cannot use pointer when gcc O2 optimizer is used */
+    tempOut = SWAP4(*ip);
 
-    unsigned int *cp = (unsigned int *) dst;
-    unsigned int *ip = (unsigned int *) src;
+    *(float *)dst = *(float *)(&tempOut);
+#endif
 
-    *cp =  ((*ip) << 24)
-        | (((*ip) & 0x0000ff00) << 8)
-        | (((*ip) & 0x00ff0000) >> 8)
-        | (((*ip) >> 24));
-*/
+    /* OLD implementation that results in four load and four store CPU
+       instructions
+    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, MPI_Offset nn)
+inline static void
+swapn4b(void *dst, const void *src, IntType nn)
 {
+    int i;
+    uint32_t *op = (uint32_t*) dst;
+    uint32_t *ip = (uint32_t*) src;
+    for (i=0; i<nn; i++) {
+        /* copy over, make the below swap in-place */
+        op[i] = ip[i];
+        op[i] = SWAP4(op[i]);
+    }
+
+#if 0
 	char *op = dst;
 	const char *ip = src;
 
@@ -252,12 +435,29 @@ swapn4b(void *dst, const void *src, MPI_Offset nn)
 		op += 4;
 		ip += 4;
 	}
+#endif
 }
 
 # ifndef vax
-static void
+inline static void
 swap8b(void *dst, const void *src)
 {
+#ifdef FLOAT_WORDS_BIGENDIAN
+    /* copy over, make the below swap in-place */
+    *(uint64_t*)dst = *(uint64_t*)src;
+
+    uint32_t *op = (uint32_t*)dst;
+    *op = SWAP4(*op);
+    op = (uint32_t*)((char*)dst+4);
+    *op = SWAP4(*op);
+#else
+    uint64_t *op = (uint64_t*)dst;
+    /* copy over, make the below swap in-place */
+    *op = *(uint64_t*)src;
+    *op = SWAP8(*op);
+#endif
+
+#if 0
 	char *op = dst;
 	const char *ip = src;
 #  ifndef FLOAT_WORDS_BIGENDIAN
@@ -279,13 +479,38 @@ swap8b(void *dst, const void *src)
 	op[6] = ip[5];
 	op[7] = ip[4];
 #endif
+#endif
 }
 # endif /* !vax */
 
 # ifndef vax
-static void
-swapn8b(void *dst, const void *src, MPI_Offset nn)
-{
+inline static void
+swapn8b(void *dst, const void *src, IntType nn)
+{
+#ifdef FLOAT_WORDS_BIGENDIAN
+    int i;
+    uint64_t *dst_p = (uint64_t*) dst;
+    uint64_t *src_p = (uint64_t*) src;
+    for (i=0; i<nn; i++) {
+        /* copy over, make the below swap in-place */
+        dst_p[i] = src_p[i];
+        uint32_t *op = (uint32_t*)(&dst_p[i]);
+        *op = SWAP4(*op);
+        op = (uint32_t*)((char*)op+4);
+        *op = SWAP4(*op);
+    }
+#else
+    int i;
+    uint64_t *op = (uint64_t*) dst;
+    uint64_t *ip = (uint64_t*) src;
+    for (i=0; i<nn; i++) {
+        /* copy over, make the below swap in-place */
+        op[i] = ip[i];
+        op[i] = SWAP8(op[i]);
+    }
+#endif
+
+#if 0
 	char *op = dst;
 	const char *ip = src;
 
@@ -355,6 +580,7 @@ swapn8b(void *dst, const void *src, MPI_Offset nn)
 		ip += 8;
 	}
 #endif
+#endif
 }
 # endif /* !vax */
 
@@ -384,44 +610,19 @@ define(`Dmin',  `ifelse(index(`$1',`u'), 0, `0', `(double)Imin($1)')')dnl
 define(`FXmin', `ifelse(index(`$1',`u'), 0, `0', `(double)Xmin($1)')')dnl
 define(`DXmin', `ifelse(index(`$1',`u'), 0, `0',         `Xmin($1)')')dnl
 
-dnl
-dnl For GET APIs:
-dnl       check for negative $3 if $1 is   signed && $2 is unsigned
-dnl Don't check for negative $3 if $1 is   signed && $2 is   signed
-dnl Don't check for negative $3 if $1 is unsigned
-dnl $5 is either "return" or "status ="
-dnl
-define(`GETI_CheckNegReturn',
-       `ifelse(index(`$1',`u'), 0, ,
-               index(`$2',`u'), 0,
-               `if ($3 < 0) DEBUG_RETURN_ERROR(NC_ERANGE) /* because $4 is unsigned */')')dnl
-
-define(`GETI_CheckNegAssign',
-       `ifelse(index(`$1',`u'), 0, ,
-               index(`$2',`u'), 0,
-               `if ($3 < 0) DEBUG_ASSIGN_ERROR(status, NC_ERANGE) /* because $4 is unsigned */')')dnl
-
 define(`Cast_Signed2Unsigned',
        `ifelse(index(`$1',`u'), 0,
                `ifelse(index(`$2',`u'), 0, , `(signed)')')')dnl
 
 dnl
-dnl For PUT APIs:
-dnl       check for negative $3 if $1 is unsigned && $2 is   signed
-dnl Don't check for negative $3 if $1 is unsigned && $2 is unsigned
-dnl Don't check for negative $3 if $1 is   signed
-dnl
-define(`PUTI_CheckNeg',
-       `ifelse(index(`$1',`u'), 0,
-               `ifelse(index(`$2',`u'), 0, ,
-                       `	if ($3 < 0) DEBUG_RETURN_ERROR(NC_ERANGE) /* because $4 is unsigned */')')')dnl
-
-dnl
 dnl For GET APIs boundary check
 dnl
 define(`GETF_CheckBND',
-`if (xx > (double)Upcase($1)_MAX || xx < Dmin($1)) DEBUG_RETURN_ERROR(NC_ERANGE)
-	*ip = ($1)xx;')
+`if (xx > (double)Upcase($1)_MAX || xx < Dmin($1)) {
+            ifdef(`ERANGE_FILL',`*ip = FillDefaultValue($1);')
+            DEBUG_RETURN_ERROR(NC_ERANGE)
+        }
+	*ip = ($1)xx;')dnl
 
 dnl
 dnl For GET APIs boudnary check for when $1 is either 'longlong' or 'ulonglong'
@@ -431,36 +632,12 @@ define(`GETF_CheckBND2',
 `if (xx == Upcase($1)_MAX)      *ip = Upcase($1)_MAX;',dnl for unsigned type
 `if (xx == Upcase($1)_MAX)      *ip = Upcase($1)_MAX;
 	else if (xx == Upcase($1)_MIN) *ip = Upcase($1)_MIN;')
-	else if (xx > (double)Upcase($1)_MAX || xx < Dmin($1)) DEBUG_RETURN_ERROR(NC_ERANGE)
+	else if (xx > (double)Upcase($1)_MAX || xx < Dmin($1)) {
+            ifdef(`ERANGE_FILL',`*ip = FillDefaultValue($1);')
+            DEBUG_RETURN_ERROR(NC_ERANGE)
+        }
 	else *ip = ($1)xx;')
 
-dnl
-dnl For PUT APIs and either $1 and $2 is float or double:
-dnl
-define(`PUTF_CheckBND',
-`ifelse(`$2', `double', `if (*ip > Xmax($1) || *ip < DXmin($1)) DEBUG_RETURN_ERROR(NC_ERANGE)',
-        `$2', `float',  `if (*ip > (double)Xmax($1) || *ip < FXmin($1)) DEBUG_RETURN_ERROR(NC_ERANGE)')')
-
-dnl
-dnl For GET APIs and $1 and $2 are not float or double
-dnl
-define(`GETI_CheckBND',
-``#'if IXmax($1) > Imax($2)
-	if (xx > Imax($2)'`ifelse(index(`$1',`u'), 0, ,
-                                  index(`$2',`u'), 0, ,
-                                  ` || xx < Imin($2)')'`) DEBUG_RETURN_ERROR(NC_ERANGE)'
-`#'endif)
-
-dnl
-dnl For PUT APIs and $1 and $2 are not float or double
-dnl
-define(`PUTI_CheckBND',
-``#'if IXmax($1) < Imax($2)
-	if (*ip > IXmax($1)'`ifelse(index(`$1',`u'), 0, ,
-                                    index(`$2',`u'), 0, ,
-                                    ` || *ip < Xmin($1)')'`) DEBUG_RETURN_ERROR(NC_ERANGE)'
-`#'endif)
-
 /*
  * Primitive numeric conversion functions.
  */
@@ -472,7 +649,7 @@ dnl
 define(`NCX_GET1F',dnl
 `dnl
 static int
-ncmpix_get_$1_$2(const void *xp, $2 *ip)
+APIPrefix`x_get_'NC_TYPE($1)_$2(const void *xp, $2 *ip)
 {
 	ix_$1 xx;
 	get_ix_$1(xp, &xx);
@@ -495,21 +672,40 @@ dnl
 define(`NCX_GET1I',dnl
 `dnl
 static int
-ncmpix_get_$1_$2(const void *xp, $2 *ip)
+APIPrefix`x_get_'NC_TYPE($1)_$2(const void *xp, $2 *ip)
 {
+    int err=NC_NOERR;
 ifelse(`$3', `1',
 ``#'if IXsizeof($1) == Isizeof($2) && IXmax($1) == Upcase($2)_MAX
-	get_ix_$1(xp, (ix_$1 *)ip);
+    get_ix_$1(xp, (ix_$1 *)ip);
 `#'else
 ')dnl
-	ix_$1 xx;
-	get_ix_$1(xp, &xx);
-GETI_CheckBND($1, $2)
-	GETI_CheckNegReturn($1, $2, xx, ip)
-	*ip = ($2) xx;
-ifelse(`$3', `1', ``#'endif
+    ix_$1 xx;
+    get_ix_$1(xp, &xx);
+
+`#'if IXmax($1) > Imax($2)
+    if (xx > Imax($2)'`ifelse(index(`$1',`u'), 0, ,
+                              index(`$2',`u'), 0, ,
+                              ` || xx < Imin($2)')'`) {
+ifdef(`ERANGE_FILL',`dnl
+        *ip = FillDefaultValue($2);
+        DEBUG_RETURN_ERROR(NC_ERANGE)',`
+        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)')
+    }'
+`#'endif
+
+`ifelse(index(`$1',`u'), 0, , index(`$2',`u'), 0,`dnl
+    if (xx < 0) {
+ifdef(`ERANGE_FILL',`dnl
+        *ip = FillDefaultValue($2);
+        DEBUG_RETURN_ERROR(NC_ERANGE)',`
+        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)') /* because ip is unsigned */
+    }')'dnl
+
+    *ip = ($2) xx;
+`ifelse(`$3', `1', ``#'endif
 ')dnl
-	return NC_NOERR;
+    return err;
 }
 ')dnl
 
@@ -520,13 +716,23 @@ dnl
 define(`NCX_PUT1F',dnl
 `dnl
 static int
-ncmpix_put_$1_$2(void *xp, const $2 *ip)
+APIPrefix`x_put_'NC_TYPE($1)_$2(void *xp, const $2 *ip, void *fillp)
 {
-	ix_$1 xx;
-	PUTF_CheckBND($1, $2)
-	xx = (ix_$1)*ip;
-	put_ix_$1(xp, &xx);
-	return NC_NOERR;
+    int err=NC_NOERR;
+    ix_$1 xx = FillDefaultValue($1);
+
+    ifelse(`$2', `double', `if (*ip > Xmax($1) || *ip < DXmin($1)) {
+        FillValue($1, &xx)
+        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
+    } ifdef(`ERANGE_FILL',`else')',
+        `$2', `float',  `if (*ip > (double)Xmax($1) || *ip < FXmin($1)) {
+        FillValue($1, &xx)
+        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
+    } ifdef(`ERANGE_FILL',`else')')
+        xx = (ix_$1)*ip;
+
+    put_ix_$1(xp, &xx);
+    return err;
 }
 ')dnl
 
@@ -537,21 +743,36 @@ dnl
 define(`NCX_PUT1I',dnl
 `dnl
 static int
-ncmpix_put_$1_$2(void *xp, const $2 *ip)
+APIPrefix`x_put_'NC_TYPE($1)_$2(void *xp, const $2 *ip, void *fillp)
 {
+    int err=NC_NOERR;
 ifelse(`$3', `1',
 ``#'if IXsizeof($1) == Isizeof($2) && IXmax($1) == Upcase($2)_MAX
-	put_ix_$1(xp, (const ix_$1 *)ip);
+    put_ix_$1(xp, (const ix_$1 *)ip);
 `#'else
 ')dnl
-	ix_$1 xx;
-PUTI_CheckBND($1, $2)
-PUTI_CheckNeg($1, $2, *ip, xp)
-	xx = (ix_$1)*ip;
-	put_ix_$1(xp, &xx);
+    ix_$1 xx = FillDefaultValue($1);
+
+`#'if IXmax($1) < Imax($2)
+    if (*ip > IXmax($1)'`ifelse(index(`$1',`u'), 0, ,
+                                index(`$2',`u'), 0, ,
+                                ` || *ip < Xmin($1)')'`) {
+        FillValue($1, &xx)
+        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
+    } ifdef(`ERANGE_FILL',`else')
+`#'endif
+ifelse(index(`$1',`u'), 0, `ifelse(index(`$2',`u'), 0, ,`dnl
+    if (*ip < 0) {
+        FillValue($1, &xx)
+        DEBUG_ASSIGN_ERROR(err, NC_ERANGE) /* because xp is unsigned */
+    } ifdef(`ERANGE_FILL',`else')
+')')dnl
+        xx = (ix_$1)*ip;
+
+    put_ix_$1(xp, &xx);
 ifelse(`$3', `1', ``#'endif
 ')dnl
-	return NC_NOERR;
+    return err;
 }
 ')dnl
 
@@ -561,7 +782,7 @@ ifelse(`$3', `1', ``#'endif
 /* We don't implement any x_schar and x_uchar primitives. */
 
 
-/* x_short -------------------------------------------------------------------*/
+/* external NC_SHORT --------------------------------------------------------*/
 
 #if SHORT_MAX == X_SHORT_MAX
 typedef short ix_short;
@@ -587,7 +808,7 @@ static void
 get_ix_short(const void *xp, ix_short *ip)
 {
 	const uchar *cp = (const uchar *) xp;
-	*ip = *cp++ << 8;
+	*ip = (ix_short)(*cp++ << 8);
 #if SIZEOF_IX_SHORT > X_SIZEOF_SHORT
 	if (*ip & 0x8000)
 	{
@@ -595,15 +816,15 @@ get_ix_short(const void *xp, ix_short *ip)
 		*ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */
 	}
 #endif
-	*ip |= *cp;
+	*ip = (ix_short)(*ip | *cp);
 }
 
 static void
 put_ix_short(void *xp, const ix_short *ip)
 {
 	uchar *cp = (uchar *) xp;
-	*cp++ = (*ip) >> 8;
-	*cp = (*ip) & 0xff;
+	*cp++ = (uchar)((*ip) >> 8);
+	*cp   = (uchar)((*ip) & 0xff);
 }
 
 NCX_GET1I(short, schar,     0)
@@ -619,7 +840,7 @@ NCX_GET1F(short, float)
 NCX_GET1F(short, double)
 
 static int
-ncmpix_put_short_schar(void *xp, const schar *ip)
+APIPrefix`x_put_'NC_TYPE(short)_schar(void *xp, const schar *ip, void *fillp)
 {
 	uchar *cp = (uchar *) xp;
 	if (*ip & 0x80)
@@ -631,7 +852,7 @@ ncmpix_put_short_schar(void *xp, const schar *ip)
 }
 
 static int
-ncmpix_put_short_uchar(void *xp, const uchar *ip)
+APIPrefix`x_put_'NC_TYPE(short)_uchar(void *xp, const uchar *ip, void *fillp)
 {
 	uchar *cp = (uchar *) xp;
 	*cp++ = 0;
@@ -649,7 +870,7 @@ NCX_PUT1I(short, ulonglong, 0)
 NCX_PUT1F(short, float)
 NCX_PUT1F(short, double)
 
-/* x_ushort ------------------------------------------------------------------*/
+/* external NC_USHORT -------------------------------------------------------*/
 
 #if USHORT_MAX == X_USHORT_MAX
 typedef unsigned short ix_ushort;
@@ -675,7 +896,7 @@ static void
 get_ix_ushort(const void *xp, ix_ushort *ip)
 {
 	const uchar *cp = (const uchar *) xp;
-	*ip = *cp++ << 8;
+	*ip = (ix_ushort)(*cp++ << 8);
 #if SIZEOF_IX_SHORT > X_SIZEOF_SHORT
 	if (*ip & 0x8000)
 	{
@@ -683,15 +904,15 @@ get_ix_ushort(const void *xp, ix_ushort *ip)
 		*ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */
 	}
 #endif
-	*ip |= *cp;
+	*ip = (ix_ushort)(*ip | *cp);
 }
 
 static void
 put_ix_ushort(void *xp, const ix_ushort *ip)
 {
 	uchar *cp = (uchar *) xp;
-	*cp++ = (*ip) >> 8;
-	*cp = (*ip) & 0xff;
+	*cp++ = (uchar)((*ip) >> 8);
+	*cp   = (uchar)((*ip) & 0xff);
 }
 
 NCX_GET1I(ushort, schar,     0)
@@ -707,22 +928,32 @@ NCX_GET1F(ushort, float)
 NCX_GET1F(ushort, double)
 
 static int
-ncmpix_put_ushort_schar(void *xp, const schar *ip)
+APIPrefix`x_put_'NC_TYPE(ushort)_schar(void *xp, const schar *ip, void *fillp)
 {
-	uchar *cp;
-        if (*ip < 0) DEBUG_RETURN_ERROR(NC_ERANGE)
-	cp = (uchar *) xp;
-	if (*ip & 0x80)
-		*cp++ = 0xff;
-	else
-		*cp++ = 0;
-	*cp = (uchar)*ip;
+    int err=NC_NOERR;
+    uchar *cp;
+    if (*ip < 0) {
+ifdef(`ERANGE_FILL', `dnl
+        if (fillp != NULL) memcpy(xp, fillp, 2);
+#ifndef WORDS_BIGENDIAN
+        swapn2b(xp, xp, 1);
+#endif
+        DEBUG_RETURN_ERROR(NC_ERANGE)',`dnl
+        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)')
+    }
 
-	return NC_NOERR;
+    cp = (uchar *) xp;
+    if (*ip & 0x80)
+        *cp++ = 0xff;
+    else
+        *cp++ = 0;
+    *cp = (uchar)*ip;
+
+    return err;
 }
 
 static int
-ncmpix_put_ushort_uchar(void *xp, const uchar *ip)
+APIPrefix`x_put_'NC_TYPE(ushort)_uchar(void *xp, const uchar *ip, void *fillp)
 {
 	uchar *cp = (uchar *) xp;
 	*cp++ = 0;
@@ -740,7 +971,7 @@ NCX_PUT1I(ushort, ulonglong, 1)
 NCX_PUT1F(ushort, float)
 NCX_PUT1F(ushort, double)
 
-/* x_int ---------------------------------------------------------------------*/
+/* external NC_INT ----------------------------------------------------------*/
 
 #if SHORT_MAX == X_INT_MAX
 typedef short ix_int;
@@ -782,10 +1013,10 @@ 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);
+	*cp++ = (uchar)( (*ip) >> 24);
+	*cp++ = (uchar)(((*ip) & 0x00ff0000) >> 16);
+	*cp++ = (uchar)(((*ip) & 0x0000ff00) >>  8);
+	*cp   = (uchar)( (*ip) & 0x000000ff);
 }
 
 #if X_SIZEOF_INT != SIZEOF_INT
@@ -803,7 +1034,7 @@ NCX_GET1F(int, float)
 NCX_GET1F(int, double)
 
 static int
-ncmpix_put_int_schar(void *xp, const schar *ip)
+APIPrefix`x_put_'NC_TYPE(int)_schar(void *xp, const schar *ip, void *fillp)
 {
 	uchar *cp = (uchar *) xp;
 	if (*ip & 0x80)
@@ -823,7 +1054,7 @@ ncmpix_put_int_schar(void *xp, const schar *ip)
 }
 
 static int
-ncmpix_put_int_uchar(void *xp, const uchar *ip)
+APIPrefix`x_put_'NC_TYPE(int)_uchar(void *xp, const uchar *ip, void *fillp)
 {
 	uchar *cp = (uchar *) xp;
 	*cp++ = 0x00;
@@ -846,7 +1077,7 @@ NCX_PUT1F(int, float)
 NCX_PUT1F(int, double)
 
 
-/* x_uint --------------------------------------------------------------------*/
+/* external NC_UINT ---------------------------------------------------------*/
 
 #if USHORT_MAX == X_UINT_MAX
 typedef ushort ix_uint;
@@ -870,10 +1101,10 @@ get_ix_uint(const void *xp, ix_uint *ip)
 {
 	const uchar *cp = (const uchar *) xp;
 
-	*ip  = (ix_uint)(*cp++ << 24);
-	*ip |= (ix_uint)(*cp++ << 16);
-	*ip |= (ix_uint)(*cp++ << 8);
-	*ip |= *cp;
+	*ip = (ix_uint)(*cp++ << 24);
+	*ip = (ix_uint)(*ip | (ix_uint)(*cp++ << 16));
+	*ip = (ix_uint)(*ip | (ix_uint)(*cp++ << 8));
+	*ip = (ix_uint)(*ip | *cp);
 }
 
 static void
@@ -881,10 +1112,10 @@ put_ix_uint(void *xp, const ix_uint *ip)
 {
 	uchar *cp = (uchar *) xp;
 
-	*cp++ = (*ip) >> 24;
-	*cp++ = ((*ip) & 0x00ff0000) >> 16;
-	*cp++ = ((*ip) & 0x0000ff00) >>  8;
-	*cp   = ((*ip) & 0x000000ff);
+	*cp++ = (uchar)((*ip) >> 24);
+	*cp++ = (uchar)(((*ip) & 0x00ff0000) >> 16);
+	*cp++ = (uchar)(((*ip) & 0x0000ff00) >>  8);
+	*cp   = (uchar)( (*ip) & 0x000000ff);
 }
 
 #if X_SIZEOF_UINT != SIZEOF_UINT
@@ -903,22 +1134,29 @@ NCX_GET1F(uint, float)
 NCX_GET1F(uint, double)
 
 static int
-ncmpix_put_uint_schar(void *xp, const schar *ip)
+APIPrefix`x_put_'NC_TYPE(uint)_schar(void *xp, const schar *ip, void *fillp)
 {
-	uchar *cp;
-	if (*ip < 0) DEBUG_RETURN_ERROR(NC_ERANGE)
+    uchar *cp;
+    if (*ip < 0) {
+ifdef(`ERANGE_FILL', `dnl
+        if (fillp != NULL) memcpy(xp, fillp, 4);
+#ifndef WORDS_BIGENDIAN
+        swapn4b(xp, xp, 1);
+#endif')
+        DEBUG_RETURN_ERROR(NC_ERANGE)
+    }
 
-	cp = (uchar *) xp;
-	*cp++ = 0x00;
-	*cp++ = 0x00;
-	*cp++ = 0x00;
-	*cp = (uchar)*ip;
+    cp = (uchar *) xp;
+    *cp++ = 0x00;
+    *cp++ = 0x00;
+    *cp++ = 0x00;
+    *cp = (uchar)*ip;
 
-	return NC_NOERR;
+    return NC_NOERR;
 }
 
 static int
-ncmpix_put_uint_uchar(void *xp, const uchar *ip)
+APIPrefix`x_put_'NC_TYPE(uint)_uchar(void *xp, const uchar *ip, void *fillp)
 {
 	uchar *cp = (uchar *) xp;
 	*cp++ = 0x00;
@@ -942,11 +1180,11 @@ NCX_PUT1F(uint, float)
 NCX_PUT1F(uint, double)
 
 
-/* x_float -------------------------------------------------------------------*/
+/* external NC_FLOAT --------------------------------------------------------*/
 
 #if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
 
-static void
+inline static void
 get_ix_float(const void *xp, float *ip)
 {
 #ifdef WORDS_BIGENDIAN
@@ -956,7 +1194,7 @@ get_ix_float(const void *xp, float *ip)
 #endif
 }
 
-static void
+inline static void
 put_ix_float(void *xp, const float *ip)
 {
 #ifdef WORDS_BIGENDIAN
@@ -1354,7 +1592,7 @@ put_ix_float(void *xp, const float *ip)
 
 #if X_SIZEOF_FLOAT != SIZEOF_FLOAT || defined(NO_IEEE_FLOAT)
 static int
-ncmpix_get_float_float(const void *xp, float *ip)
+APIPrefix`x_get_'NC_TYPE(float)_float(const void *xp, float *ip, void *fillp)
 {
 	/* TODO */
 	get_ix_float(xp, ip);
@@ -1377,14 +1615,20 @@ NCX_GET1F(float, ulonglong)
 
 #if X_SIZEOF_FLOAT != SIZEOF_FLOAT || defined(NO_IEEE_FLOAT)
 static int
-ncmpix_put_float_float(void *xp, const float *ip)
+APIPrefix`x_put_'NC_TYPE(float)_float(void *xp, const float *ip, void *fillp)
 {
+    int err=NC_NOERR;
+    float *_ip=ip;
 #ifdef NO_IEEE_FLOAT
-	if (*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN)
-		DEBUG_RETURN_ERROR(NC_ERANGE)
+    ifdef(`ERANGE_FILL',`float tmp;')
+    if (*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) {
+        FillValue(float, &tmp)
+        ifdef(`ERANGE_FILL',`_ip = &tmp;')
+        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
+    }
 #endif
-	put_ix_float(xp, ip);
-	return NC_NOERR;
+    put_ix_float(xp, _ip);
+    return err;
 }
 #endif
 
@@ -1400,7 +1644,7 @@ NCX_PUT1F(float, uint)
 NCX_PUT1F(float, ulonglong)
 
 
-/* x_double ------------------------------------------------------------------*/
+/* external NC_DOUBLE -------------------------------------------------------*/
 
 #if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE  && !defined(NO_IEEE_FLOAT)
 
@@ -1690,27 +1934,25 @@ NCX_GET1F(double, uint)
 NCX_GET1F(double, ulonglong)
 
 static int
-ncmpix_get_double_float(const void *xp, float *ip)
+APIPrefix`x_get_'NC_TYPE(double)_float(const void *xp, float *ip)
 {
-	double xx;
-	get_ix_double(xp, &xx);
-	if (xx > FLT_MAX)
-	{
-		*ip = FLT_MAX;
-		DEBUG_RETURN_ERROR(NC_ERANGE)
-	}
-	if (xx < (-FLT_MAX))
-	{
-		*ip = (-FLT_MAX);
-		DEBUG_RETURN_ERROR(NC_ERANGE)
-	}
-	*ip = (float) xx;
-	return NC_NOERR;
+    double xx;
+    get_ix_double(xp, &xx);
+    if (xx > FLT_MAX) {
+        ifdef(`ERANGE_FILL', `*ip = NC_FILL_FLOAT;', `*ip = FLT_MAX;')
+        DEBUG_RETURN_ERROR(NC_ERANGE)
+    }
+    if (xx < (-FLT_MAX)) {
+        ifdef(`ERANGE_FILL', `*ip = NC_FILL_FLOAT;', `*ip = (-FLT_MAX);')
+        DEBUG_RETURN_ERROR(NC_ERANGE)
+    }
+    *ip = (float) xx;
+    return NC_NOERR;
 }
 
 #if X_SIZEOF_DOUBLE != SIZEOF_DOUBLE  || defined(NO_IEEE_FLOAT)
 static int
-ncmpix_get_double_double(const void *xp, double *ip)
+APIPrefix`x_get_'NC_TYPE(double)_double(const void *xp, double *ip, void *fillp)
 {
 	/* TODO */
 	get_ix_double(xp, ip);
@@ -1729,32 +1971,43 @@ NCX_PUT1F(double, longlong)
 NCX_PUT1F(double, ulonglong)
 
 static int
-ncmpix_put_double_float(void *xp, const float *ip)
+APIPrefix`x_put_'NC_TYPE(double)_float(void *xp, const float *ip, void *fillp)
 {
-#if 0	/* TODO: figure this out (if condition below will never be true)*/
-	if ((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN)
-		DEBUG_RETURN_ERROR(NC_ERANGE)
+    int err=NC_NOERR;
+    double xx = FillDefaultValue(double);
+#if 1	/* TODO: figure this out (if condition below will never be true)*/
+    if ((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) {
+        FillValue(double, &xx)
+        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
+    } ifdef(`ERANGE_FILL',`else')
 #endif
-	double xx = (double) *ip;
-	put_ix_double(xp, &xx);
-	return NC_NOERR;
+        xx = (double) *ip;
+
+    put_ix_double(xp, &xx);
+    return err;
 }
 
 #if X_SIZEOF_DOUBLE != SIZEOF_DOUBLE  || defined(NO_IEEE_FLOAT)
 static int
-ncmpix_put_double_double(void *xp, const double *ip)
+APIPrefix`x_put_'NC_TYPE(double)_double(void *xp, const double *ip, void *fillp)
 {
+    int err=NC_NOERR;
+    double *_ip = ip;
 #ifdef NO_IEEE_FLOAT
-	if (*ip > X_DOUBLE_MAX || *ip < X_DOUBLE_MIN)
-		DEBUG_RETURN_ERROR(NC_ERANGE)
+    ifdef(`ERANGE_FILL',`double tmp=NC_FILL_DOUBLE;')
+    if (*ip > X_DOUBLE_MAX || *ip < X_DOUBLE_MIN) {
+        FillValue(double, &tmp)
+        ifdef(`ERANGE_FILL',`_ip = &tmp;')
+        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
+    }
 #endif
-	put_ix_double(xp, ip);
-	return NC_NOERR;
+    put_ix_double(xp, _ip);
+    return err;
 }
 #endif
 
 
-/* x_int64 -------------------------------------------------------------------*/
+/* external NC_INT64 --------------------------------------------------------*/
 
 #if SHORT_MAX == X_INT64_MAX
 typedef short ix_int64;
@@ -1793,14 +2046,14 @@ put_ix_int64(void *xp, const ix_int64 *ip)
 {
     uchar *cp = (uchar *) xp;
 
-    *cp++ = (*ip) >> 56;
-    *cp++ = ((*ip) & 0x00ff000000000000LL) >> 48;
-    *cp++ = ((*ip) & 0x0000ff0000000000LL) >> 40;
-    *cp++ = ((*ip) & 0x000000ff00000000LL) >> 32;
-    *cp++ = ((*ip) & 0x00000000ff000000LL) >> 24;
-    *cp++ = ((*ip) & 0x0000000000ff0000LL) >> 16;
-    *cp++ = ((*ip) & 0x000000000000ff00LL) >>  8;
-    *cp   = ((*ip) & 0x00000000000000ffLL);
+    *cp++ = (uchar)((*ip) >> 56);
+    *cp++ = (uchar)(((*ip) & 0x00ff000000000000LL) >> 48);
+    *cp++ = (uchar)(((*ip) & 0x0000ff0000000000LL) >> 40);
+    *cp++ = (uchar)(((*ip) & 0x000000ff00000000LL) >> 32);
+    *cp++ = (uchar)(((*ip) & 0x00000000ff000000LL) >> 24);
+    *cp++ = (uchar)(((*ip) & 0x0000000000ff0000LL) >> 16);
+    *cp++ = (uchar)(((*ip) & 0x000000000000ff00LL) >>  8);
+    *cp   = (uchar)( (*ip) & 0x00000000000000ffLL);
 }
 
 #if X_SIZEOF_INT64 != SIZEOF_LONGLONG
@@ -1832,7 +2085,7 @@ NCX_PUT1F(int64, float)
 NCX_PUT1F(int64, double)
 
 
-/* x_uint64 -----------------------------------------------------------------*/
+/* external NC_UINT64 -------------------------------------------------------*/
 
 #if USHORT_MAX == X_UINT64_MAX
 typedef ushort ix_uint64;
@@ -1871,14 +2124,14 @@ put_ix_uint64(void *xp, const ix_uint64 *ip)
 {
     uchar *cp = (uchar *) xp;
 
-    *cp++ = (*ip) >> 56;
-    *cp++ = ((*ip) & 0x00ff000000000000ULL) >> 48;
-    *cp++ = ((*ip) & 0x0000ff0000000000ULL) >> 40;
-    *cp++ = ((*ip) & 0x000000ff00000000ULL) >> 32;
-    *cp++ = ((*ip) & 0x00000000ff000000ULL) >> 24;
-    *cp++ = ((*ip) & 0x0000000000ff0000ULL) >> 16;
-    *cp++ = ((*ip) & 0x000000000000ff00ULL) >>  8;
-    *cp   = ((*ip) & 0x00000000000000ffULL);
+    *cp++ = (uchar)((*ip) >> 56);
+    *cp++ = (uchar)(((*ip) & 0x00ff000000000000ULL) >> 48);
+    *cp++ = (uchar)(((*ip) & 0x0000ff0000000000ULL) >> 40);
+    *cp++ = (uchar)(((*ip) & 0x000000ff00000000ULL) >> 32);
+    *cp++ = (uchar)(((*ip) & 0x00000000ff000000ULL) >> 24);
+    *cp++ = (uchar)(((*ip) & 0x0000000000ff0000ULL) >> 16);
+    *cp++ = (uchar)(((*ip) & 0x000000000000ff00ULL) >>  8);
+    *cp   = (uchar)( (*ip) & 0x00000000000000ffULL);
 }
 
 #if X_SIZEOF_UINT64 != SIZEOF_ULONGLONG
@@ -1918,7 +2171,7 @@ NCX_PUT1F(uint64, double)
 #endif
 
 int
-ncmpix_put_size_t(void **xpp, const size_t *ulp)
+APIPrefix`x_put_size_t'(void **xpp, const size_t *ulp)
 {
 	/* similar to put_ix_int() */
 	uchar *cp = (uchar *) *xpp;
@@ -1934,7 +2187,7 @@ ncmpix_put_size_t(void **xpp, const size_t *ulp)
 }
 
 int
-ncmpix_get_size_t(const void **xpp,  size_t *ulp)
+APIPrefix`x_get_size_t'(const void **xpp,  size_t *ulp)
 {
 	/* similar to get_ix_int */
 	const uchar *cp = (const uchar *) *xpp;
@@ -1951,7 +2204,7 @@ ncmpix_get_size_t(const void **xpp,  size_t *ulp)
 /* x_off_t */
 
 int
-ncmpix_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t)
+APIPrefix`x_put_off_t'(void **xpp, const off_t *lp, size_t sizeof_off_t)
 {
 	/* No negative offsets stored in netcdf */
 	if (*lp < 0) {
@@ -1997,7 +2250,7 @@ ncmpix_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t)
 }
 
 int
-ncmpix_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t)
+APIPrefix`x_get_off_t'(const void **xpp, off_t *lp, size_t sizeof_off_t)
 {
 	/* similar to get_ix_int() */
 	const uchar *cp = (const uchar *) *xpp;
@@ -2053,21 +2306,21 @@ ncmpix_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t)
 	return NC_NOERR;
 }
 
-/*----< ncmpix_get_uint32() >-------------------------------------------------*/
+/*----< APIPrefix`x_get_uint32'() >------------------------------------------*/
 int
-ncmpix_get_uint32(const void **xpp, uint *ip)
+APIPrefix`x_get_uint32'(const void **xpp, uint *ip)
 {
 #ifdef WORDS_BIGENDIAN
     /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
      * some system, such as HPUX */
-    (void) memcpy(ip, *xpp, X_SIZEOF_INT);
+    (void) memcpy(ip, *xpp, SIZEOF_UINT);
 #else
     const uchar *cp = (const uchar *) *xpp;
 
-    *ip  = (*cp++ << 24);
-    *ip |= (*cp++ << 16);
-    *ip |= (*cp++ <<  8);
-    *ip |=  *cp;
+    *ip = (uint)(*cp++ << 24);
+    *ip = (uint)(*ip | (uint)(*cp++ << 16));
+    *ip = (uint)(*ip | (uint)(*cp++ <<  8));
+    *ip = (uint)(*ip | *cp);
 #endif
     /* advance *xpp 4 bytes */
     *xpp = (void *)((const char *)(*xpp) + 4);
@@ -2075,26 +2328,26 @@ ncmpix_get_uint32(const void **xpp, uint *ip)
     return NC_NOERR;
 }
 
-/*----< ncmpix_get_uint64() >-------------------------------------------------*/
+/*----< APIPrefix`x_get_uint64'() >------------------------------------------*/
 int
-ncmpix_get_uint64(const void **xpp, unsigned long long *llp)
+APIPrefix`x_get_uint64'(const void **xpp, unsigned long long *ullp)
 {
 #ifdef WORDS_BIGENDIAN
     /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
      * some system, such as HPUX */
-    (void) memcpy(llp, *xpp, X_SIZEOF_INT64);
+    (void) memcpy(ullp, *xpp, SIZEOF_UINT64);
 #else
     const uchar *cp = (const uchar *) *xpp;
 
-    /* below is the same as calling swap8b(llp, *xpp) */
-    *llp  = ((long long)(*cp++) << 56);
-    *llp |= ((long long)(*cp++) << 48);
-    *llp |= ((long long)(*cp++) << 40);
-    *llp |= ((long long)(*cp++) << 32);
-    *llp |= ((long long)(*cp++) << 24);
-    *llp |= ((long long)(*cp++) << 16);
-    *llp |= ((long long)(*cp++) <<  8);
-    *llp |=  (long long)*cp;
+    /* below is the same as calling swap8b(ullp, *xpp) */
+    *ullp = (unsigned long long)(*cp++) << 56;
+    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 48);
+    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 40);
+    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 32);
+    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 24);
+    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 16);
+    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) <<  8);
+    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp));
 #endif
     /* advance *xpp 8 bytes */
     *xpp = (void *)((const char *)(*xpp) + 8);
@@ -2102,17 +2355,17 @@ ncmpix_get_uint64(const void **xpp, unsigned long long *llp)
     return NC_NOERR;
 }
 
-/*---< ncmpix_put_uint32() >--------------------------------------------------*/
+/*---< APIPrefix`x_put_uint32'() >-------------------------------------------*/
 /* copy the contents of ip (an unsigned 32-bit integer) to xpp in Big Endian
  * form and advance *xpp 4 bytes
  */
 int
-ncmpix_put_uint32(void **xpp, const unsigned int ip)
+APIPrefix`x_put_uint32'(void **xpp, const unsigned int ip)
 {
 #ifdef WORDS_BIGENDIAN
     /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
      * some system, such as HPUX */
-    (void) memcpy(*xpp, &ip, X_SIZEOF_INT);
+    (void) memcpy(*xpp, &ip, X_SIZEOF_UINT);
 #else
     /* bitwise shifts below are to produce an integer in Big Endian */
     uchar *cp = (uchar *) *xpp;
@@ -2127,17 +2380,17 @@ ncmpix_put_uint32(void **xpp, const unsigned int ip)
     return NC_NOERR;
 }
 
-/*---< ncmpix_put_uint64() >--------------------------------------------------*/
+/*---< APIPrefix`x_put_uint64'() >-------------------------------------------*/
 /* copy the contents of ip (an unsigned 64-bit integer) to xpp in Big Endian
  * form and advance *xpp 8 bytes
  */
 int
-ncmpix_put_uint64(void **xpp, const unsigned long long ip)
+APIPrefix`x_put_uint64'(void **xpp, const unsigned long long ip)
 {
 #ifdef WORDS_BIGENDIAN
     /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
      * some system, such as HPUX */
-    (void) memcpy(*xpp, &ip, X_SIZEOF_INT64);
+    (void) memcpy(*xpp, &ip, X_SIZEOF_UINT64);
 #else
     uchar *cp = (uchar *) *xpp;
     /* below is the same as calling swap8b(*xpp, &ip) */
@@ -2181,7 +2434,7 @@ dnl NCX_PAD_GETN_Byte_body (body for one byte types on diagonal)
 dnl
 define(`NCX_PAD_GETN_Byte_Body',dnl
 `dnl
-	MPI_Offset rndup = nelems % X_ALIGN;
+	IntType rndup = nelems % X_ALIGN;
 
 	if (rndup)
 		rndup = X_ALIGN - rndup;
@@ -2193,91 +2446,72 @@ define(`NCX_PAD_GETN_Byte_Body',dnl
 ')dnl
 dnl dnl dnl
 dnl
-dnl NCX_GETN_CHAR(Type)
+dnl NCX_GETN_BYTE(xtype, itype)
 dnl
-define(`NCX_GETN_CHAR',dnl
+define(`NCX_GETN_BYTE',dnl
 `dnl
 int
-ncmpix_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
+APIPrefix`x_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp)
 {
-	int status = NC_NOERR;
-	$1 *xp = ($1 *)(*xpp);
+    int status = NC_NOERR;
+    $1 *xp = ($1 *)(*xpp);
 
-	while (nelems-- != 0)
-	{
-		GETI_CheckNegAssign($1, $2, *xp, tp)
-		*tp++ = ($2) Cast_Signed2Unsigned($2,$1) (*xp++);  /* type cast from $1 to $2 */
-		/* TODO: skip the assignment if NC_ERANGE occurs?
-		 * However, if doing so, many nc_test/nf_test will fail
-		 */
-	}
+    while (nelems-- != 0) {
+        ifelse(index(`$1',`u'), 0, ,
+               index(`$2',`u'), 0, `
+        if (*xp < 0) {
+            ifdef(`ERANGE_FILL',`*tp = FillDefaultValue($2);')
+            DEBUG_ASSIGN_ERROR(status, NC_ERANGE) /* because tp is unsigned */
+            SKIP_LOOP(xp, tp)
+        }')dnl
 
-	*xpp = (const void *)xp;
-	return status;
+        *tp++ = ($2) Cast_Signed2Unsigned($2,$1) (*xp++);  /* type cast from $1 to $2 */
+    }
+
+    *xpp = (const void *)xp;
+    return status;
 }
 ')dnl
 dnl dnl dnl
 dnl
-dnl NCX_PAD_GETN_CHAR(Type)
+dnl NCX_PAD_GETN_BYTE(xtype, itype)
 dnl
-define(`NCX_PAD_GETN_CHAR',dnl
+define(`NCX_PAD_GETN_BYTE',dnl
 `dnl
 int
-ncmpix_pad_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
+APIPrefix`x_pad_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp)
 {
-	int status = NC_NOERR;
-	MPI_Offset rndup = nelems % X_ALIGN;
-	$1 *xp = ($1 *) *xpp;
+    int status = NC_NOERR;
+    IntType rndup = nelems % X_ALIGN;
+    $1 *xp = ($1 *) *xpp;
 
-	if (rndup)
-		rndup = X_ALIGN - rndup;
+    if (rndup)
+        rndup = X_ALIGN - rndup;
 
-	while (nelems-- != 0)
-	{
-		GETI_CheckNegAssign($1, $2, *xp, tp)
-		*tp++ = ($2) Cast_Signed2Unsigned($2,$1) (*xp++);  /* type cast from $1 to $2 */
-		/* TODO: skip the assignment if NC_ERANGE occurs?
-		 * However, if doing so, many nc_test/nf_test will fail
-		 */
-	}
+    while (nelems-- != 0) {
+        ifelse(index(`$1',`u'), 0, ,
+               index(`$2',`u'), 0, `
+        if (*xp < 0) {
+            ifdef(`ERANGE_FILL', `*tp = FillDefaultValue($2);')
+            DEBUG_ASSIGN_ERROR(status, NC_ERANGE) /* because tp is unsigned */
+            SKIP_LOOP(xp, tp)
+        }')dnl
 
-	*xpp = (void *)(xp + rndup);
-	return status;
-}
-')dnl
-dnl dnl dnl
-dnl
-dnl NCX_GETNo(XType, Type) deprecated
-dnl
-define(`NCX_GETNo',dnl
-`dnl
-int
-ncmpix_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
-{
-	const char *xp = (const char *) *xpp;
-	int status = NC_NOERR;
-	$1 xx;
-
-	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
-	{
-		const int lstatus = ncmpix_get_$1_$1(xp, &xx);
-		*tp = ($2)xx;
-		if (status == NC_NOERR) /* report the first encountered error */
-			status = lstatus;
-	}
+        *tp++ = ($2) Cast_Signed2Unsigned($2,$1) (*xp++);  /* type cast from $1 to $2 */
+    }
 
-	*xpp = (const void *)xp;
-	return status;
+    *xpp = (void *)(xp + rndup);
+    return status;
 }
 ')dnl
 dnl dnl dnl
 dnl
-dnl NCX_GETN(XType, Type, condition)
+dnl NCX_GETN(xtype, itype)
 dnl
 define(`NCX_GETN',dnl
 `dnl
 int
-ncmpix_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
+APIPrefix`x_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp)
 {
 `#'if defined(_SX) && _SX != 0 && Xsizeof($1) == Isizeof($1)
 
@@ -2331,7 +2565,7 @@ ncmpix_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
 
 	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
 	{
-		const int lstatus = ncmpix_get_$1_$2(xp, tp);
+		const int lstatus = APIPrefix`x_get_'NC_TYPE($1)_$2(xp, tp);
 		if (status == NC_NOERR) /* report the first encountered error */
 			status = lstatus;
 	}
@@ -2348,16 +2582,16 @@ dnl
 define(`NCX_PAD_GETN_SHORT',dnl
 `dnl
 int
-ncmpix_pad_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
+APIPrefix`x_pad_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp)
 {
-	const MPI_Offset rndup = nelems % 2;
+	const IntType rndup = nelems % X_SIZEOF_SHORT;
 
 	const char *xp = (const char *) *xpp;
 	int status = NC_NOERR;
 
 	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
 	{
-		const int lstatus = ncmpix_get_$1_$2(xp, tp);
+		const int lstatus = APIPrefix`x_get_'NC_TYPE($1)_$2(xp, tp);
 		if (status == NC_NOERR) /* report the first encountered error */
 			status = lstatus;
 	}
@@ -2385,7 +2619,7 @@ dnl
 dnl NCX_PAD_PUTN_Byte_Body(Type) (body for one byte types)
 dnl
 define(`NCX_PAD_PUTN_Byte_Body',dnl
-	MPI_Offset rndup = nelems % X_ALIGN;
+	IntType rndup = nelems % X_ALIGN;
 
 	if (rndup)
 		rndup = X_ALIGN - rndup;
@@ -2404,102 +2638,71 @@ define(`NCX_PAD_PUTN_Byte_Body',dnl
 ')dnl
 dnl dnl dnl
 dnl
-dnl NCX_PUTN_CHAR(Type)
+dnl NCX_PUTN_BYTE(xtype, itype)
 dnl
-define(`NCX_PUTN_CHAR',dnl
+define(`NCX_PUTN_BYTE',dnl
 `dnl
 int
-ncmpix_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
+APIPrefix`x_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp)
 {
-	int status = NC_NOERR;
-	$1 *xp = ($1 *) *xpp;
+    int status = NC_NOERR;
+    $1 *xp = ($1 *) *xpp;
 
-	while (nelems-- != 0)
-	{
-		if (*tp > ($2)Xmax($1) ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)'))
-			DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
-		*xp++ = ($1) Cast_Signed2Unsigned($1,$2) *tp++; /* type cast from $2 to $1 */
-		/* TODO: skip the assignment if NC_ERANGE occurs?
-		 * However, if doing so, many nc_test/nf_test will fail
-		 */
-	}
+    while (nelems-- != 0) {
+        if (*tp > ($2)Xmax($1) ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)')) {
+            FillValue($1, xp)
+            DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+            SKIP_LOOP(xp, tp)
+        }
+        *xp++ = ($1) Cast_Signed2Unsigned($1,$2) *tp++; /* type cast from $2 to $1 */
+    }
 
-	*xpp = (void *)xp;
-	return status;
+    *xpp = (void *)xp;
+    return status;
 }
 ')dnl
 dnl dnl dnl
 dnl
-dnl NCX_PAD_PUTN_CHAR(xtype, ttype)
+dnl NCX_PAD_PUTN_BYTE(xtype, ttype)
 dnl
-define(`NCX_PAD_PUTN_CHAR',dnl
+define(`NCX_PAD_PUTN_BYTE',dnl
 `dnl
 int
-ncmpix_pad_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
+APIPrefix`x_pad_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp)
 {
-	int status = NC_NOERR;
-	MPI_Offset rndup = nelems % X_ALIGN;
-	$1 *xp = ($1 *) *xpp;
-
-	if (rndup)
-		rndup = X_ALIGN - rndup;
+    int status = NC_NOERR;
+    IntType rndup = nelems % X_ALIGN;
+    $1 *xp = ($1 *) *xpp;
 
-	while (nelems-- != 0)
-	{
-		if (*tp > ($2)Xmax($1) ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)'))
-			DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
-		*xp++ = ($1) Cast_Signed2Unsigned($1,$2) *tp++; /* type cast from $2 to $1 */
-		/* TODO: skip the assignment if NC_ERANGE occurs?
-		 * However, if doing so, many nc_test/nf_test will fail
-		 */
-	}
+    if (rndup) rndup = X_ALIGN - rndup;
 
+    while (nelems-- != 0) {
+        if (*tp > ($2)Xmax($1) ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)')) {
+            FillValue($1, xp)
+            DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+            SKIP_LOOP(xp, tp)
+        }
+        *xp++ = ($1) Cast_Signed2Unsigned($1,$2) *tp++; /* type cast from $2 to $1 */
+    }
 
-	if (rndup)
-	{
-		(void) memcpy(xp, nada, (size_t)rndup);
-		xp += rndup;
-	}
 
-	*xpp = (void *)xp;
-	return status;
-}
-')dnl
-dnl dnl dnl
-dnl
-dnl NCX_PUTNo(XType, Type) deprecated
-dnl
-define(`NCX_PUTNo',dnl
-`dnl
-int
-ncmpix_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
-{
-	char *xp = (char *) *xpp;
-	int status = NC_NOERR;
-	$1 xx;
-
-	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
-	{
-		xx = ($1) *tp;
-		{
-		int lstatus = ncmpix_put_$1_$1(xp, &xx);
-		if (status == NC_NOERR) /* report the first encountered error */
-			status = lstatus;
-		}
-	}
+    if (rndup) {
+        (void) memcpy(xp, nada, (size_t)rndup);
+        xp += rndup;
+    }
 
-	*xpp = (void *)xp;
-	return status;
+    *xpp = (void *)xp;
+    return status;
 }
 ')dnl
 dnl dnl dnl
 dnl
-dnl NCX_PUTN(XType, Type, condition)
+dnl NCX_PUTN(xtype, itype)
 dnl
 define(`NCX_PUTN',dnl
 `dnl
 int
-ncmpix_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
+APIPrefix`x_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp)
 {
 `#'if defined(_SX) && _SX != 0 && Xsizeof($1) == Isizeof($1)
 
@@ -2515,7 +2718,7 @@ ncmpix_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
   $1 *xp;
 ifelse( $1$2, intfloat,dnl
 `dnl
-  double d;               /* special case for ncmpix_putn_int_float */
+  double d;               /* special case for APIPrefix`x_putn_int_float' */
 ')dnl
   int nrange = 0;         /* number of range errors */
   int realign = 0;        /* "do we need to fix input data alignment?" */
@@ -2554,7 +2757,7 @@ ifelse( $1$2, intfloat,dnl
     }
    /* copy workspace back if necessary */
     if (realign) {
-      memcpy(*xpp, tmp, (size_t)*ni*Xsizeof($1)));
+      memcpy(*xpp, tmp, (size_t)*ni*Xsizeof($1));
       xp = ($1 *) *xpp;
     }
    /* update xpp and tp */
@@ -2571,7 +2774,7 @@ ifelse( $1$2, intfloat,dnl
 
 	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
 	{
-		int lstatus = ncmpix_put_$1_$2(xp, tp);
+		int lstatus = APIPrefix`x_put_'NC_TYPE($1)_$2(xp, tp, fillp);
 		if (status == NC_NOERR) /* report the first encountered error */
 			status = lstatus;
 	}
@@ -2588,16 +2791,16 @@ dnl
 define(`NCX_PAD_PUTN_SHORT',dnl
 `dnl
 int
-ncmpix_pad_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
+APIPrefix`x_pad_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp)
 {
-	const MPI_Offset rndup = nelems % 2;
+	const IntType rndup = nelems % X_SIZEOF_SHORT;
 
 	char *xp = (char *) *xpp;
 	int status = NC_NOERR;
 
 	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
 	{
-		int lstatus = ncmpix_put_$1_$2(xp, tp);
+		int lstatus = APIPrefix`x_put_'NC_TYPE($1)_$2(xp, tp, fillp);
 		if (status == NC_NOERR) /* report the first encountered error */
 			status = lstatus;
 	}
@@ -2621,262 +2824,234 @@ dnl dnl dnl
 
 /* schar ---------------------------------------------------------------------*/
 
-dnl NCX_GETN_CHAR(schar, schar)
+dnl NCX_GETN_BYTE(schar, schar)
 int
-ncmpix_getn_schar_schar(const void **xpp, MPI_Offset nelems, schar *tp)
+APIPrefix`x_getn_'NC_TYPE(schar)_schar(const void **xpp, IntType nelems, schar *tp)
 {
 	NCX_GETN_Byte_Body
 }
-dnl NCX_GETN_CHAR(schar, uchar)
-int
-ncmpix_getn_schar_uchar(const void **xpp, MPI_Offset nelems, uchar *tp)
-{
-	NCX_GETN_Byte_Body
-}
-NCX_GETN_CHAR(schar, short)
-NCX_GETN_CHAR(schar, int)
-NCX_GETN_CHAR(schar, long)
-NCX_GETN_CHAR(schar, float)
-NCX_GETN_CHAR(schar, double)
-NCX_GETN_CHAR(schar, longlong)
-NCX_GETN_CHAR(schar, ushort)
-NCX_GETN_CHAR(schar, uint)
-NCX_GETN_CHAR(schar, ulonglong)
-
-dnl NCX_PAD_GETN_CHAR(schar, schar)
-int
-ncmpix_pad_getn_schar_schar(const void **xpp, MPI_Offset nelems, schar *tp)
-{
-	NCX_PAD_GETN_Byte_Body
-}
-dnl NCX_PAD_GETN_CHAR(schar, uchar)
+NCX_GETN_BYTE(schar, uchar)
+NCX_GETN_BYTE(schar, short)
+NCX_GETN_BYTE(schar, int)
+NCX_GETN_BYTE(schar, long)
+NCX_GETN_BYTE(schar, float)
+NCX_GETN_BYTE(schar, double)
+NCX_GETN_BYTE(schar, longlong)
+NCX_GETN_BYTE(schar, ushort)
+NCX_GETN_BYTE(schar, uint)
+NCX_GETN_BYTE(schar, ulonglong)
+
+dnl NCX_PAD_GETN_BYTE(schar, schar)
 int
-ncmpix_pad_getn_schar_uchar(const void **xpp, MPI_Offset nelems, uchar *tp)
+APIPrefix`x_pad_getn_'NC_TYPE(schar)_schar(const void **xpp, IntType nelems, schar *tp)
 {
 	NCX_PAD_GETN_Byte_Body
 }
-NCX_PAD_GETN_CHAR(schar, short)
-NCX_PAD_GETN_CHAR(schar, int)
-NCX_PAD_GETN_CHAR(schar, long)
-NCX_PAD_GETN_CHAR(schar, float)
-NCX_PAD_GETN_CHAR(schar, double)
-NCX_PAD_GETN_CHAR(schar, longlong)
-NCX_PAD_GETN_CHAR(schar, ushort)
-NCX_PAD_GETN_CHAR(schar, uint)
-NCX_PAD_GETN_CHAR(schar, ulonglong)
-
-dnl NCX_PUTN_CHAR(schar, schar)
-int
-ncmpix_putn_schar_schar(void **xpp, MPI_Offset nelems, const schar *tp)
-{
-	NCX_PUTN_Byte_Body
-}
-dnl NCX_PUTN_CHAR(schar, uchar)
+NCX_PAD_GETN_BYTE(schar, uchar)
+NCX_PAD_GETN_BYTE(schar, short)
+NCX_PAD_GETN_BYTE(schar, int)
+NCX_PAD_GETN_BYTE(schar, long)
+NCX_PAD_GETN_BYTE(schar, float)
+NCX_PAD_GETN_BYTE(schar, double)
+NCX_PAD_GETN_BYTE(schar, longlong)
+NCX_PAD_GETN_BYTE(schar, ushort)
+NCX_PAD_GETN_BYTE(schar, uint)
+NCX_PAD_GETN_BYTE(schar, ulonglong)
+
+dnl NCX_PUTN_BYTE(schar, schar)
 int
-ncmpix_putn_schar_uchar(void **xpp, MPI_Offset nelems, const uchar *tp)
+APIPrefix`x_putn_'NC_TYPE(schar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp)
 {
 	NCX_PUTN_Byte_Body
 }
-NCX_PUTN_CHAR(schar, short)
-NCX_PUTN_CHAR(schar, int)
-NCX_PUTN_CHAR(schar, long)
-NCX_PUTN_CHAR(schar, float)
-NCX_PUTN_CHAR(schar, double)
-NCX_PUTN_CHAR(schar, longlong)
-NCX_PUTN_CHAR(schar, ushort)
-NCX_PUTN_CHAR(schar, uint)
-NCX_PUTN_CHAR(schar, ulonglong)
-
-dnl NCX_PAD_PUTN_CHAR(schar, schar)
-int
-ncmpix_pad_putn_schar_schar(void **xpp, MPI_Offset nelems, const schar *tp)
-{
-	NCX_PAD_PUTN_Byte_Body
-}
-dnl NCX_PAD_PUTN_CHAR(schar, uchar)
+NCX_PUTN_BYTE(schar, uchar)
+NCX_PUTN_BYTE(schar, short)
+NCX_PUTN_BYTE(schar, int)
+NCX_PUTN_BYTE(schar, long)
+NCX_PUTN_BYTE(schar, float)
+NCX_PUTN_BYTE(schar, double)
+NCX_PUTN_BYTE(schar, longlong)
+NCX_PUTN_BYTE(schar, ushort)
+NCX_PUTN_BYTE(schar, uint)
+NCX_PUTN_BYTE(schar, ulonglong)
+
+dnl NCX_PAD_PUTN_BYTE(schar, schar)
 int
-ncmpix_pad_putn_schar_uchar(void **xpp, MPI_Offset nelems, const uchar *tp)
+APIPrefix`x_pad_putn_'NC_TYPE(schar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp)
 {
 	NCX_PAD_PUTN_Byte_Body
 }
-NCX_PAD_PUTN_CHAR(schar, short)
-NCX_PAD_PUTN_CHAR(schar, int)
-NCX_PAD_PUTN_CHAR(schar, long)
-NCX_PAD_PUTN_CHAR(schar, float)
-NCX_PAD_PUTN_CHAR(schar, double)
-NCX_PAD_PUTN_CHAR(schar, longlong)
-NCX_PAD_PUTN_CHAR(schar, ushort)
-NCX_PAD_PUTN_CHAR(schar, uint)
-NCX_PAD_PUTN_CHAR(schar, ulonglong)
+NCX_PAD_PUTN_BYTE(schar, uchar)
+NCX_PAD_PUTN_BYTE(schar, short)
+NCX_PAD_PUTN_BYTE(schar, int)
+NCX_PAD_PUTN_BYTE(schar, long)
+NCX_PAD_PUTN_BYTE(schar, float)
+NCX_PAD_PUTN_BYTE(schar, double)
+NCX_PAD_PUTN_BYTE(schar, longlong)
+NCX_PAD_PUTN_BYTE(schar, ushort)
+NCX_PAD_PUTN_BYTE(schar, uint)
+NCX_PAD_PUTN_BYTE(schar, ulonglong)
 
 
 /* uchar ---------------------------------------------------------------------*/
 dnl
-dnl NCX_GETN_CHAR(uchar, schar)
+dnl NCX_GETN_BYTE(uchar, schar)
 int
-ncmpix_getn_uchar_schar(const void **xpp, MPI_Offset nelems, schar *tp)
+APIPrefix`x_getn_'NC_TYPE(uchar)_schar(const void **xpp, IntType nelems, schar *tp)
 {
-	int status = NC_NOERR;
-	uchar *xp = (uchar *)(*xpp);
+    int status = NC_NOERR;
+    uchar *xp = (uchar *)(*xpp);
 
-	while (nelems-- != 0)
-	{
-		if (*xp > SCHAR_MAX)
-			DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
-		*tp++ = (schar) *xp++; /* type cast from uchar to schar */
-		/* TODO: skip the assignment if NC_ERANGE occurs?
-		 * However, if doing so, many nc_test/nf_test will fail
-		 */
-	}
+    while (nelems-- != 0) {
+        if (*xp > SCHAR_MAX) {
+            *tp = NC_FILL_BYTE;
+       	    DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+            SKIP_LOOP(xp, tp)
+        }
+	*tp++ = (schar) *xp++; /* type cast from uchar to schar */
+    }
 
-	*xpp = (const void *)xp;
-	return status;
+    *xpp = (const void *)xp;
+    return status;
 }
-dnl NCX_GETN_CHAR(uchar, uchar)
+dnl NCX_GETN_BYTE(uchar, uchar)
 int
-ncmpix_getn_uchar_uchar(const void **xpp, MPI_Offset nelems, uchar *tp)
+APIPrefix`x_getn_'NC_TYPE(uchar)_uchar(const void **xpp, IntType nelems, uchar *tp)
 {
 	NCX_GETN_Byte_Body
 }
-NCX_GETN_CHAR(uchar, short)
-NCX_GETN_CHAR(uchar, int)
-NCX_GETN_CHAR(uchar, long)
-NCX_GETN_CHAR(uchar, float)
-NCX_GETN_CHAR(uchar, double)
-NCX_GETN_CHAR(uchar, longlong)
-NCX_GETN_CHAR(uchar, ushort)
-NCX_GETN_CHAR(uchar, uint)
-NCX_GETN_CHAR(uchar, ulonglong)
-
-dnl NCX_PAD_GETN_CHAR(uchar, schar)
+NCX_GETN_BYTE(uchar, short)
+NCX_GETN_BYTE(uchar, int)
+NCX_GETN_BYTE(uchar, long)
+NCX_GETN_BYTE(uchar, float)
+NCX_GETN_BYTE(uchar, double)
+NCX_GETN_BYTE(uchar, longlong)
+NCX_GETN_BYTE(uchar, ushort)
+NCX_GETN_BYTE(uchar, uint)
+NCX_GETN_BYTE(uchar, ulonglong)
+
+dnl NCX_PAD_GETN_BYTE(uchar, schar)
 int
-ncmpix_pad_getn_uchar_schar(const void **xpp, MPI_Offset nelems, schar *tp)
-{
-        int status = NC_NOERR;
-        MPI_Offset rndup = nelems % X_ALIGN;
-        uchar *xp = (uchar *) *xpp;
-        
-        if (rndup)
-                rndup = X_ALIGN - rndup;
-        
-        while (nelems-- != 0)
-        {       
-                if (*xp > SCHAR_MAX)
-                        DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
-                *tp++ = (schar) *xp++; /* type cast from uchar to schar */
-                /* TODO: skip the assignment if NC_ERANGE occurs?
-                 * However, if doing so, many nc_test/nf_test will fail
-                 */
+APIPrefix`x_pad_getn_'NC_TYPE(uchar)_schar(const void **xpp, IntType nelems, schar *tp)
+{
+    int status = NC_NOERR;
+    IntType rndup = nelems % X_ALIGN;
+    uchar *xp = (uchar *) *xpp;
+
+    if (rndup) rndup = X_ALIGN - rndup;
+
+    while (nelems-- != 0) {
+        if (*xp > SCHAR_MAX) {
+            *tp = NC_FILL_BYTE;
+            DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+            SKIP_LOOP(xp, tp)
         }
-        
-        *xpp = (void *)(xp + rndup);
-        return status;
+        *tp++ = (schar) *xp++; /* type cast from uchar to schar */
+    }
+
+    *xpp = (void *)(xp + rndup);
+    return status;
 }
-dnl NCX_PAD_GETN_CHAR(uchar, uchar)
+dnl NCX_PAD_GETN_BYTE(uchar, uchar)
 int
-ncmpix_pad_getn_uchar_uchar(const void **xpp, MPI_Offset nelems, uchar *tp)
+APIPrefix`x_pad_getn_'NC_TYPE(uchar)_uchar(const void **xpp, IntType nelems, uchar *tp)
 {
 	NCX_PAD_GETN_Byte_Body
 }
-NCX_PAD_GETN_CHAR(uchar, short)
-NCX_PAD_GETN_CHAR(uchar, int)
-NCX_PAD_GETN_CHAR(uchar, long)
-NCX_PAD_GETN_CHAR(uchar, float)
-NCX_PAD_GETN_CHAR(uchar, double)
-NCX_PAD_GETN_CHAR(uchar, longlong)
-NCX_PAD_GETN_CHAR(uchar, ushort)
-NCX_PAD_GETN_CHAR(uchar, uint)
-NCX_PAD_GETN_CHAR(uchar, ulonglong)
-
-dnl NCX_PUTN_CHAR(uchar, schar)
+NCX_PAD_GETN_BYTE(uchar, short)
+NCX_PAD_GETN_BYTE(uchar, int)
+NCX_PAD_GETN_BYTE(uchar, long)
+NCX_PAD_GETN_BYTE(uchar, float)
+NCX_PAD_GETN_BYTE(uchar, double)
+NCX_PAD_GETN_BYTE(uchar, longlong)
+NCX_PAD_GETN_BYTE(uchar, ushort)
+NCX_PAD_GETN_BYTE(uchar, uint)
+NCX_PAD_GETN_BYTE(uchar, ulonglong)
+
+dnl NCX_PUTN_BYTE(uchar, schar)
 int
-ncmpix_putn_uchar_schar(void **xpp, MPI_Offset nelems, const schar *tp)
+APIPrefix`x_putn_'NC_TYPE(uchar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp)
 {
-	int status = NC_NOERR;
-	uchar *xp = (uchar *) *xpp;
+    int status = NC_NOERR;
+    uchar *xp = (uchar *) *xpp;
 
-	while (nelems-- != 0)
-	{
-		if (*tp < 0)
-			DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
-		*xp++ = (uchar) (signed) *tp++; /* type cast from schar to uchar */
-		/* TODO: skip the assignment if NC_ERANGE occurs?
-		 * However, if doing so, many nc_test/nf_test will fail
-		 */
-	}
+    while (nelems-- != 0) {
+        if (*tp < 0) {
+            FillValue(uchar, xp)
+            DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+            SKIP_LOOP(xp, tp)
+        }
+        *xp++ = (uchar) (signed) *tp++; /* type cast from schar to uchar */
+    }
 
-	*xpp = (void *)xp;
-	return status;
+    *xpp = (void *)xp;
+    return status;
 }
-dnl NCX_PUTN_CHAR(uchar, uchar)
+dnl NCX_PUTN_BYTE(uchar, uchar)
 int
-ncmpix_putn_uchar_uchar(void **xpp, MPI_Offset nelems, const uchar *tp)
+APIPrefix`x_putn_'NC_TYPE(uchar)_uchar(void **xpp, IntType nelems, const uchar *tp, void *fillp)
 {
 	NCX_PUTN_Byte_Body
 }
-NCX_PUTN_CHAR(uchar, short)
-NCX_PUTN_CHAR(uchar, int)
-NCX_PUTN_CHAR(uchar, long)
-NCX_PUTN_CHAR(uchar, float)
-NCX_PUTN_CHAR(uchar, double)
-NCX_PUTN_CHAR(uchar, longlong)
-NCX_PUTN_CHAR(uchar, ushort)
-NCX_PUTN_CHAR(uchar, uint)
-NCX_PUTN_CHAR(uchar, ulonglong)
-
-dnl NCX_PAD_PUTN_UCHAR(uchar, schar)
+NCX_PUTN_BYTE(uchar, short)
+NCX_PUTN_BYTE(uchar, int)
+NCX_PUTN_BYTE(uchar, long)
+NCX_PUTN_BYTE(uchar, float)
+NCX_PUTN_BYTE(uchar, double)
+NCX_PUTN_BYTE(uchar, longlong)
+NCX_PUTN_BYTE(uchar, ushort)
+NCX_PUTN_BYTE(uchar, uint)
+NCX_PUTN_BYTE(uchar, ulonglong)
+
+dnl NCX_PAD_PUTN_BYTE(uchar, schar)
 int
-ncmpix_pad_putn_uchar_schar(void **xpp, MPI_Offset nelems, const schar *tp)
+APIPrefix`x_pad_putn_'NC_TYPE(uchar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp)
 {
-	int status = NC_NOERR;
-	MPI_Offset rndup = nelems % X_ALIGN;
-	uchar *xp = (uchar *) *xpp;
-
-	if (rndup)
-		rndup = X_ALIGN - rndup;
+    int status = NC_NOERR;
+    IntType rndup = nelems % X_ALIGN;
+    uchar *xp = (uchar *) *xpp;
 
-	while (nelems-- != 0)
-	{
-		if (*tp < 0)
-			DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
-		*xp++ = (uchar) (signed) *tp++; /* type cast from schar to uchar */
-		/* TODO: skip the assignment if NC_ERANGE occurs?
-		 * However, if doing so, many nc_test/nf_test will fail
-		 */
-	}
+    if (rndup) rndup = X_ALIGN - rndup;
 
+    while (nelems-- != 0) {
+        if (*tp < 0) {
+            FillValue(uchar, xp)
+            DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+            SKIP_LOOP(xp, tp)
+        }
+        *xp++ = (uchar) (signed) *tp++; /* type cast from schar to uchar */
+    }
 
-	if (rndup)
-	{
-		(void) memcpy(xp, nada, (size_t)rndup);
-		xp += rndup;
-	}
+    if (rndup) {
+        (void) memcpy(xp, nada, (size_t)rndup);
+        xp += rndup;
+    }
 
-	*xpp = (void *)xp;
-	return status;
+    *xpp = (void *)xp;
+    return status;
 }
 dnl NCX_PAD_PUTN_UCHAR(uchar, uchar)
 int
-ncmpix_pad_putn_uchar_uchar(void **xpp, MPI_Offset nelems, const uchar *tp)
+APIPrefix`x_pad_putn_'NC_TYPE(uchar)_uchar(void **xpp, IntType nelems, const uchar *tp, void *fillp)
 {
 	NCX_PAD_PUTN_Byte_Body
 }
-NCX_PAD_PUTN_CHAR(uchar, short)
-NCX_PAD_PUTN_CHAR(uchar, int)
-NCX_PAD_PUTN_CHAR(uchar, long)
-NCX_PAD_PUTN_CHAR(uchar, float)
-NCX_PAD_PUTN_CHAR(uchar, double)
-NCX_PAD_PUTN_CHAR(uchar, longlong)
-NCX_PAD_PUTN_CHAR(uchar, ushort)
-NCX_PAD_PUTN_CHAR(uchar, uint)
-NCX_PAD_PUTN_CHAR(uchar, ulonglong)
+NCX_PAD_PUTN_BYTE(uchar, short)
+NCX_PAD_PUTN_BYTE(uchar, int)
+NCX_PAD_PUTN_BYTE(uchar, long)
+NCX_PAD_PUTN_BYTE(uchar, float)
+NCX_PAD_PUTN_BYTE(uchar, double)
+NCX_PAD_PUTN_BYTE(uchar, longlong)
+NCX_PAD_PUTN_BYTE(uchar, ushort)
+NCX_PAD_PUTN_BYTE(uchar, uint)
+NCX_PAD_PUTN_BYTE(uchar, ulonglong)
 
 /* short ---------------------------------------------------------------------*/
 
 #if X_SIZEOF_SHORT == SIZEOF_SHORT
 /* optimized version */
 int
-ncmpix_getn_short_short(const void **xpp, MPI_Offset nelems, short *tp)
+APIPrefix`x_getn_'NC_TYPE(short)_short(const void **xpp, IntType nelems, short *tp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_SHORT);
@@ -2915,7 +3090,7 @@ NCX_PAD_GETN_SHORT(short, ushort)
 #if X_SIZEOF_SHORT == SIZEOF_SHORT
 /* optimized version */
 int
-ncmpix_putn_short_short(void **xpp, MPI_Offset nelems, const short *tp)
+APIPrefix`x_putn_'NC_TYPE(short)_short(void **xpp, IntType nelems, const short *tp, void *fillp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_SHORT);
@@ -2957,10 +3132,10 @@ NCX_PAD_PUTN_SHORT(short, ushort)
 #if X_SIZEOF_USHORT == SIZEOF_USHORT
 /* optimized version */
 int
-ncmpix_getn_ushort_ushort(const void **xpp, MPI_Offset nelems, unsigned short *tp)
+APIPrefix`x_getn_'NC_TYPE(ushort)_ushort(const void **xpp, IntType nelems, unsigned short *tp)
 {
 #ifdef WORDS_BIGENDIAN
-	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_UNSIGNED_SHORT);
+	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_USHORT);
 # else
 	swapn2b(tp, *xpp, nelems);
 # endif
@@ -2996,7 +3171,7 @@ NCX_PAD_GETN_SHORT(ushort, ulonglong)
 #if X_SIZEOF_USHORT == SIZEOF_USHORT
 /* optimized version */
 int
-ncmpix_putn_ushort_ushort(void **xpp, MPI_Offset nelems, const unsigned short *tp)
+APIPrefix`x_putn_'NC_TYPE(ushort)_ushort(void **xpp, IntType nelems, const unsigned short *tp, void *fillp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_USHORT);
@@ -3038,7 +3213,7 @@ NCX_PAD_PUTN_SHORT(ushort, ushort)
 #if X_SIZEOF_INT == SIZEOF_INT
 /* optimized version */
 int
-ncmpix_getn_int_int(const void **xpp, MPI_Offset nelems, int *tp)
+APIPrefix`x_getn_'NC_TYPE(int)_int(const void **xpp, IntType nelems, int *tp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_INT);
@@ -3065,7 +3240,7 @@ NCX_GETN(int, ulonglong)
 #if X_SIZEOF_INT == SIZEOF_INT
 /* optimized version */
 int
-ncmpix_putn_int_int(void **xpp, MPI_Offset nelems, const int *tp)
+APIPrefix`x_putn_'NC_TYPE(int)_int(void **xpp, IntType nelems, const int *tp, void *fillp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_INT);
@@ -3094,7 +3269,7 @@ NCX_PUTN(int, ulonglong)
 #if X_SIZEOF_UINT == SIZEOF_UINT
 /* optimized version */
 int
-ncmpix_getn_uint_uint(const void **xpp, MPI_Offset nelems, unsigned int *tp)
+APIPrefix`x_getn_'NC_TYPE(uint)_uint(const void **xpp, IntType nelems, unsigned int *tp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_UINT);
@@ -3121,7 +3296,7 @@ NCX_GETN(uint, ulonglong)
 #if X_SIZEOF_UINT == SIZEOF_UINT
 /* optimized version */
 int
-ncmpix_putn_uint_uint(void **xpp, MPI_Offset nelems, const unsigned int *tp)
+APIPrefix`x_putn_'NC_TYPE(uint)_uint(void **xpp, IntType nelems, const unsigned int *tp, void *fillp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_UINT);
@@ -3151,7 +3326,7 @@ NCX_PUTN(uint, ulonglong)
 #if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
 /* optimized version */
 int
-ncmpix_getn_float_float(const void **xpp, MPI_Offset nelems, float *tp)
+APIPrefix`x_getn_'NC_TYPE(float)_float(const void **xpp, IntType nelems, float *tp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_FLOAT);
@@ -3163,7 +3338,7 @@ ncmpix_getn_float_float(const void **xpp, MPI_Offset nelems, float *tp)
 }
 #elif defined(vax) && vax != 0
 int
-ncmpix_getn_float_float(const void **xpp, MPI_Offset nfloats, float *ip)
+APIPrefix`x_getn_'NC_TYPE(float)_float(const void **xpp, IntType nfloats, float *ip)
 {
 	float *const end = ip + nfloats;
 
@@ -3178,14 +3353,14 @@ GET_VAX_DFLOAT_Body(`(*xpp)')
 }
 #else
 int
-ncmpix_getn_float_float(const void **xpp, MPI_Offset nelems, float *tp)
+APIPrefix`x_getn_'NC_TYPE(float)_float(const void **xpp, IntType nelems, float *tp)
 {
 	const char *xp = *xpp;
 	int status = NC_NOERR;
 
 	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
 	{
-		const int lstatus = ncmpix_get_float_float(xp, tp);
+		const int lstatus = APIPrefix`x_get_'NC_TYPE(float)_float(xp, tp, fillp);
 		if (status == NC_NOERR) /* report the first encountered error */
 			status = lstatus;
 	}
@@ -3206,10 +3381,10 @@ NCX_GETN(float, uchar)
 NCX_GETN(float, uint)
 NCX_GETN(float, ulonglong)
 
+int
+APIPrefix`x_putn_'NC_TYPE(float)_float(void **xpp, IntType nelems, const float *tp, void *fillp)
 #if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
 /* optimized version */
-int
-ncmpix_putn_float_float(void **xpp, MPI_Offset nelems, const float *tp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_FLOAT);
@@ -3220,30 +3395,23 @@ ncmpix_putn_float_float(void **xpp, MPI_Offset nelems, const float *tp)
 	return NC_NOERR;
 }
 #elif defined(vax) && vax != 0
-int
-ncmpix_putn_float_float(void **xpp, MPI_Offset nfloats, const float *ip)
 {
-	const float *const end = ip + nfloats;
-
-	while (ip < end)
-	{
-PUT_VAX_DFLOAT_Body(`(*xpp)')
+	const float *const end = tp + nelems;
 
-		ip++;
+	while (tp < end) {
+		PUT_VAX_DFLOAT_Body(`(*xpp)')
+		tp++;
 		*xpp = (char *)(*xpp) + X_SIZEOF_FLOAT;
 	}
 	return NC_NOERR;
 }
 #else
-int
-ncmpix_putn_float_float(void **xpp, MPI_Offset nelems, const float *tp)
 {
 	char *xp = *xpp;
 	int status = NC_NOERR;
 
-	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
-	{
-		int lstatus = ncmpix_put_float_float(xp, tp);
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) {
+		int lstatus = APIPrefix`x_put_'NC_TYPE(float)_float(xp, tp, fillp);
 		if (status == NC_NOERR) /* report the first encountered error */
 			status = lstatus;
 	}
@@ -3268,7 +3436,7 @@ NCX_PUTN(float, ulonglong)
 #if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT)
 /* optimized version */
 int
-ncmpix_getn_double_double(const void **xpp, MPI_Offset nelems, double *tp)
+APIPrefix`x_getn_'NC_TYPE(double)_double(const void **xpp, IntType nelems, double *tp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_DOUBLE);
@@ -3280,7 +3448,7 @@ ncmpix_getn_double_double(const void **xpp, MPI_Offset nelems, double *tp)
 }
 #elif defined(vax) && vax != 0
 int
-ncmpix_getn_double_double(const void **xpp, MPI_Offset ndoubles, double *ip)
+APIPrefix`x_getn_'NC_TYPE(double)_double(const void **xpp, IntType ndoubles, double *ip)
 {
 	double *const end = ip + ndoubles;
 
@@ -3295,14 +3463,14 @@ GET_VAX_DDOUBLE_Body(`(*xpp)')
 	/* vax */
 #else
 int
-ncmpix_getn_double_double(const void **xpp, MPI_Offset nelems, double *tp)
+APIPrefix`x_getn_'NC_TYPE(double)_double(const void **xpp, IntType nelems, double *tp)
 {
 	const char *xp = *xpp;
 	int status = NC_NOERR;
 
 	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
 	{
-		const int lstatus = ncmpix_get_double_double(xp, tp);
+		const int lstatus = APIPrefix`x_get_'NC_TYPE(double)_double(xp, tp, fillp);
 		if (status == NC_NOERR) /* report the first encountered error */
 			status = lstatus;
 	}
@@ -3325,7 +3493,7 @@ NCX_GETN(double, ulonglong)
 #if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT)
 /* optimized version */
 int
-ncmpix_putn_double_double(void **xpp, MPI_Offset nelems, const double *tp)
+APIPrefix`x_putn_'NC_TYPE(double)_double(void **xpp, IntType nelems, const double *tp, void *fillp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_DOUBLE);
@@ -3337,7 +3505,7 @@ ncmpix_putn_double_double(void **xpp, MPI_Offset nelems, const double *tp)
 }
 #elif defined(vax) && vax != 0
 int
-ncmpix_putn_double_double(void **xpp, MPI_Offset ndoubles, const double *ip)
+APIPrefix`x_putn_'NC_TYPE(double)_double(void **xpp, IntType ndoubles, const double *ip, void *fillp)
 {
 	const double *const end = ip + ndoubles;
 
@@ -3352,14 +3520,14 @@ PUT_VAX_DDOUBLE_Body(`(*xpp)')
 	/* vax */
 #else
 int
-ncmpix_putn_double_double(void **xpp, MPI_Offset nelems, const double *tp)
+APIPrefix`x_putn_'NC_TYPE(double)_double(void **xpp, IntType nelems, const double *tp, void *fillp)
 {
 	char *xp = *xpp;
 	int status = NC_NOERR;
 
 	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
 	{
-		int lstatus = ncmpix_put_double_double(xp, tp);
+		int lstatus = APIPrefix`x_put_'NC_TYPE(double)_double(xp, tp, fillp);
 		if (status == NC_NOERR) /* report the first encountered error */
 			status = lstatus;
 	}
@@ -3385,7 +3553,7 @@ NCX_PUTN(double, ulonglong)
 #if X_SIZEOF_INT64 == SIZEOF_LONGLONG
 /* optimized version */
 int
-ncmpix_getn_int64_longlong(const void **xpp, MPI_Offset nelems, long long *tp)
+APIPrefix`x_getn_'NC_TYPE(int64)_longlong(const void **xpp, IntType nelems, long long *tp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_LONG_LONG);
@@ -3412,7 +3580,7 @@ NCX_GETN(int64, ulonglong)
 #if X_SIZEOF_INT64 == SIZEOF_LONGLONG
 /* optimized version */
 int
-ncmpix_putn_int64_longlong(void **xpp, MPI_Offset nelems, const long long *tp)
+APIPrefix`x_putn_'NC_TYPE(int64)_longlong(void **xpp, IntType nelems, const long long *tp, void *fillp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_INT64);
@@ -3441,7 +3609,7 @@ NCX_PUTN(int64, ulonglong)
 #if X_SIZEOF_UINT64 == SIZEOF_ULONGLONG
 /* optimized version */
 int
-ncmpix_getn_uint64_ulonglong(const void **xpp, MPI_Offset nelems, unsigned long long *tp)
+APIPrefix`x_getn_'NC_TYPE(uint64)_ulonglong(const void **xpp, IntType nelems, unsigned long long *tp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_UNSIGNED_LONG_LONG);
@@ -3468,7 +3636,7 @@ NCX_GETN(uint64, uint)
 #if X_SIZEOF_UINT64 == SIZEOF_ULONGLONG
 /* optimized version */
 int
-ncmpix_putn_uint64_ulonglong(void **xpp, MPI_Offset nelems, const unsigned long long *tp)
+APIPrefix`x_putn_'NC_TYPE(uint64)_ulonglong(void **xpp, IntType nelems, const unsigned long long *tp, void *fillp)
 {
 #ifdef WORDS_BIGENDIAN
 	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_UINT64);
@@ -3500,25 +3668,25 @@ NCX_PUTN(uint64, uint)
 /* text */
 
 int
-ncmpix_getn_text(const void **xpp, MPI_Offset nelems, char *tp)
+APIPrefix`x_getn_text'(const void **xpp, IntType nelems, char *tp)
 {
 NCX_GETN_Byte_Body
 }
 
 int
-ncmpix_pad_getn_text(const void **xpp, MPI_Offset nelems, char *tp)
+APIPrefix`x_pad_getn_text'(const void **xpp, IntType nelems, char *tp)
 {
 NCX_PAD_GETN_Byte_Body
 }
 
 int
-ncmpix_putn_text(void **xpp, MPI_Offset nelems, const char *tp)
+APIPrefix`x_putn_text'(void **xpp, IntType nelems, const char *tp)
 {
 NCX_PUTN_Byte_Body
 }
 
 int
-ncmpix_pad_putn_text(void **xpp, MPI_Offset nelems, const char *tp)
+APIPrefix`x_pad_putn_text'(void **xpp, IntType nelems, const char *tp)
 {
 NCX_PAD_PUTN_Byte_Body
 }
@@ -3527,25 +3695,25 @@ NCX_PAD_PUTN_Byte_Body
 /* opaque */
 
 int
-ncmpix_getn_void(const void **xpp, MPI_Offset nelems, void *tp)
+APIPrefix`x_getn_void'(const void **xpp, IntType nelems, void *tp)
 {
 NCX_GETN_Byte_Body
 }
 
 int
-ncmpix_pad_getn_void(const void **xpp, MPI_Offset nelems, void *tp)
+APIPrefix`x_pad_getn_void'(const void **xpp, IntType nelems, void *tp)
 {
 NCX_PAD_GETN_Byte_Body
 }
 
 int
-ncmpix_putn_void(void **xpp, MPI_Offset nelems, const void *tp)
+APIPrefix`x_putn_void'(void **xpp, IntType nelems, const void *tp)
 {
 NCX_PUTN_Byte_Body
 }
 
 int
-ncmpix_pad_putn_void(void **xpp, MPI_Offset nelems, const void *tp)
+APIPrefix`x_pad_putn_void'(void **xpp, IntType nelems, const void *tp)
 {
 NCX_PAD_PUTN_Byte_Body
 }
diff --git a/src/lib/ncx_h.m4 b/src/lib/ncx_h.m4
new file mode 100644
index 0000000..e61a01a
--- /dev/null
+++ b/src/lib/ncx_h.m4
@@ -0,0 +1,381 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* "$Id: ncx_h.m4 2582 2016-10-27 18:40:10Z wkliao $" */
+
+#ifndef _NCX_H_
+#define _NCX_H_
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncio.h"
+#include "fbits.h"
+#include "nctypes.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 "rnd.h"
+#include <stddef.h> /* size_t */
+#include <errno.h>
+#include <sys/types.h> /* off_t */
+
+
+#if defined(_CRAY) && !defined(_CRAYIEEE) && !defined(__crayx1)
+#define CRAYFLOAT 1 /* CRAY Floating point */
+#elif defined(_SX) && defined(_FLOAT2)	/* NEC SUPER-UX in CRAY mode */
+#define CRAYFLOAT 1 /* CRAY Floating point */
+#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
+
+/* additional data types in CDF-5 */
+#define X_SIZEOF_UBYTE		1
+#define X_SIZEOF_USHORT		2
+#define X_SIZEOF_UINT		4
+#define X_SIZEOF_LONGLONG	8
+#define X_SIZEOF_ULONGLONG	8
+#define X_SIZEOF_INT64		8
+#define X_SIZEOF_UINT64		8
+
+/*
+ * For now, netcdf is limited to 32 bit sizes,
+ * If compiled with support for "large files", then
+ * netcdf will use a 64 bit off_t and it can then write a file
+ * using 64 bit offsets.
+ *  see also X_SIZE_MAX, X_OFF_MAX below
+ */
+/* #define X_SIZEOF_OFF_T		(sizeof(off_t)) */
+#define X_SIZEOF_OFF_T		SIZEOF_OFF_T
+#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
+#define X_LONGLONG_MIN	(-9223372036854775807LL-1LL)
+#define X_LONGLONG_MAX	9223372036854775807LL
+#define X_ULONGLONG_MAX	18446744073709551615ULL
+#define X_FLOAT_MAX	3.402823466e+38f
+#define X_FLOAT_MIN	(-X_FLOAT_MAX)
+#define X_FLT_MAX	X_FLOAT_MAX	/* alias compatible with limits.h */
+#if defined(CRAYFLOAT) && CRAYFLOAT != 0
+/* 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_UINT_MAX
+#define X_OFF_MAX	X_INT_MAX
+
+
+/* Begin ncmpix_len */
+
+/*
+ * ncmpix_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 ncmpix_len_char(nelems) \
+	_RNDUP((nelems), X_ALIGN)
+
+#define ncmpix_len_short(nelems) \
+	(((nelems) + (nelems)%2)  * X_SIZEOF_SHORT)
+
+#define ncmpix_len_int(nelems) \
+	((nelems) * X_SIZEOF_INT)
+
+#define ncmpix_len_long(nelems) \
+	((nelems) * X_SIZEOF_LONG)
+
+#define ncmpix_len_float(nelems) \
+	((nelems) * X_SIZEOF_FLOAT)
+
+#define ncmpix_len_double(nelems) \
+	((nelems) * X_SIZEOF_DOUBLE)
+
+#define ncmpix_len_ubyte(nelems) \
+	_RNDUP((nelems), X_ALIGN)
+
+#define ncmpix_len_ushort(nelems) \
+	(((nelems) + (nelems)%2)  * X_SIZEOF_USHORT)
+
+#define ncmpix_len_uint(nelems) \
+	((nelems) * X_SIZEOF_UINT)
+
+#define ncmpix_len_int64(nelems) \
+	((nelems) * X_SIZEOF_INT64)
+
+#define ncmpix_len_uint64(nelems) \
+	((nelems) * X_SIZEOF_UINT64)
+
+/* End ncmpix_len */
+
+#if defined(__CHAR_UNSIGNED__) && __CHAR_UNSIGNED__ != 0
+	/* '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 ncmpix_get_{external_type}_{internal_type}(
+ *		const void *xp,
+ *		internal_type *ip
+ *	);
+ *	int ncmpix_put_{external_type}_{internal_type}(
+ *		void *xp,
+ *		const internal_type *ip
+ *	);
+ * where
+ *	``external_type'' chosen from
+ *      	NC_CHAR
+ *      	NC_BYTE
+ *      	NC_SHORT
+ *      	NC_INT
+ *      	NC_FLOAT
+ *      	NC_DOUBLE
+ *      	NC_UBYTE
+ *      	NC_USHORT
+ *      	NC_UINT
+ *      	NC_INT64
+ *      	NC_UINT64
+ *
+ *	``internal_type'' chosen from
+ *      	schar
+ *      	uchar
+ *      	short
+ *      	int
+ *      	float
+ *      	double
+ *      	ushort
+ *      	uint
+ *      	longlong
+ *      	ulonglong
+ *
+ * Not all combinations make sense, i.e. those causing NC_ECHAR.
+ * We may not implement all combinations that make sense.
+ * The netcdf functions that use this ncmpix interface do not
+ * 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 NC_NOERR 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.
+ *
+ */
+
+/*
+ * Other primitive conversion functions
+ * N.B. slightly different interface
+ * Used by netcdf.
+ */
+
+/* ncmpix_get_int_size_t */
+extern int
+ncmpix_get_size_t(const void **xpp, size_t *ulp);
+/* ncmpix_get_int_off_t */
+extern int
+ncmpix_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t);
+
+/* ncmpix_put_int_size_t */
+extern int
+ncmpix_put_size_t(void **xpp, const size_t *ulp);
+/* ncmpix_put_int_off_t */
+extern int
+ncmpix_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t);
+
+extern int
+ncmpix_get_uint32(const void **xpp, unsigned int *ip);
+extern int
+ncmpix_get_uint64(const void **xpp, unsigned long long *ip);
+extern int
+ncmpix_put_uint32(void **xpp, const unsigned int ip);
+extern int
+ncmpix_put_uint64(void **xpp, const unsigned long long ip);
+
+
+/*
+ * 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 ncmpix_getn_{external_type}_{internal_type}(
+ *		const void *xpp,
+ *		size_t nelems,
+ *		internal_type *ip
+ *	);
+ *	int ncmpix_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.
+ *
+ */
+
+include(`foreach.m4')
+
+dnl
+dnl CONV_GET_XTYPE_ITYPE(op, xtype, itype)
+dnl
+define(`CONV_GET_XTYPE_ITYPE',dnl
+`dnl
+extern int
+ncmpix_$1_$2_$3(const void **xpp, MPI_Offset nelems, $3 *ip);
+')dnl
+dnl
+dnl CONV_PUT_XTYPE_ITYPE(op, xtype, itype)
+dnl
+define(`CONV_PUT_XTYPE_ITYPE',dnl
+`dnl
+extern int
+ncmpix_$1_$2_$3(void **xpp, MPI_Offset nelems, const $3 *ip, void *fillp);
+')dnl
+dnl
+define(`_concat3', $1$2$3)dnl
+dnl
+dnl for external types that need padding
+foreach(`xtype', (NC_BYTE, NC_UBYTE, NC_SHORT, NC_USHORT),
+`/*---- xtype ----------------------------------------------------------------*/
+foreach(`op', (getn, pad_getn),
+`foreach(`itype', (schar, uchar, short, ushort, int, uint, long, float, double, longlong, ulonglong),
+                  `_concat3(CONV_GET_XTYPE_ITYPE(op,xtype,itype))')
+')dnl
+foreach(`op', (putn, pad_putn),
+`foreach(`itype', (schar, uchar, short, ushort, int, uint, long, float, double, longlong, ulonglong),
+                  `_concat3(CONV_PUT_XTYPE_ITYPE(op,xtype,itype))')
+')'dnl
+)
+dnl
+dnl for external types that need no padding
+foreach(`xtype', (NC_INT, NC_UINT, NC_FLOAT, NC_DOUBLE, NC_INT64, NC_UINT64),
+`/*---- xtype ----------------------------------------------------------------*/
+foreach(`op', (getn),
+`foreach(`itype', (schar, uchar, short, ushort, int, uint, long, float, double, longlong, ulonglong),
+                  `_concat3(CONV_GET_XTYPE_ITYPE(op,xtype,itype))')
+')dnl
+foreach(`op', (putn),
+`foreach(`itype', (schar, uchar, short, ushort, int, uint, long, float, double, longlong, ulonglong),
+                  `_concat3(CONV_PUT_XTYPE_ITYPE(op,xtype,itype))')
+')'dnl
+)
+dnl
+/*
+ * Other aggregate conversion functions.
+ */
+
+/* read ASCII characters */
+extern int
+ncmpix_getn_text(const void **xpp, MPI_Offset nchars, char *cp);
+extern int
+ncmpix_pad_getn_text(const void **xpp, MPI_Offset nchars, char *cp);
+
+/* write ASCII characters */
+extern int
+ncmpix_putn_text(void **xpp, MPI_Offset nchars, const char *cp);
+extern int
+ncmpix_pad_putn_text(void **xpp, MPI_Offset nchars, const char *cp);
+
+/* for symmetry */
+#define ncmpix_getn_char_char(xpp, nelems, fillp) ncmpix_getn_text(xpp, nelems, fillp)
+#define ncmpix_putn_char_char(xpp, nelems, fillp) ncmpix_putn_text(xpp, nelems, fillp)
+
+/* read opaque data */
+extern int
+ncmpix_getn_void(const void **xpp, MPI_Offset nchars, void *vp);
+extern int
+ncmpix_pad_getn_void(const void **xpp, MPI_Offset nchars, void *vp);
+
+/* write opaque data */
+extern int
+ncmpix_putn_void(void **xpp, MPI_Offset nchars, const void *vp);
+extern int
+ncmpix_pad_putn_void(void **xpp, MPI_Offset nchars, const void *vp);
+
+#endif /* _NCX_H_ */
diff --git a/src/lib/nonblocking.c b/src/lib/nonblocking.c
index 1578de2..bf0cac3 100644
--- a/src/lib/nonblocking.c
+++ b/src/lib/nonblocking.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: nonblocking.c 2330 2016-03-02 12:56:52Z wkliao $ */
+/* $Id: nonblocking.c 2588 2016-10-30 04:14:15Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -31,8 +31,8 @@
 */
 
 /* Prototypes for functions used only in this file */
-static int ncmpii_wait_getput(NC *ncp, int num_reqs, NC_req *req_head,
-                              int rw_flag, int io_method);
+static int ncmpii_wait_getput(NC *ncp, int num_reqs, NC_req *reqs, int rw_flag,
+                              int io_method, MPI_Offset newnumrecs);
 
 static int ncmpii_mgetput(NC *ncp, int num_reqs, NC_req *reqs, int rw_flag,
                           int io_method);
@@ -112,18 +112,14 @@ ncmpii_abuf_coalesce(NC *ncp)
 }
 
 #define FREE_REQUEST(req) {                                                   \
-    if (req->abuf_index >= 0)                                                 \
-        ncp->abuf->occupy_table[req->abuf_index].is_used = 0; /* mark free */ \
-    else if (req->xbuf != NULL && req->xbuf != req->buf)                      \
-        NCI_Free(req->xbuf);                                                  \
-    req->xbuf = NULL;                                                         \
-                                                                              \
-    for (j=0; j<req->num_subreqs; j++)                                        \
-        NCI_Free(req->subreqs[j].start);                                      \
-                                                                              \
-    if (req->num_subreqs > 0)                                                 \
-        NCI_Free(req->subreqs);                                               \
-    NCI_Free(req->start);                                                     \
+    if (req.num_recs > 0) {                                                   \
+        if (req.abuf_index >= 0)                                              \
+            ncp->abuf->occupy_table[req.abuf_index].is_used = 0; /* free */   \
+        else if (req.xbuf != NULL && req.xbuf != req.buf)                     \
+            NCI_Free(req.xbuf);                                               \
+    }                                                                         \
+    req.xbuf = NULL;                                                          \
+    NCI_Free(req.start);                                                      \
 }
 
 /*----< ncmpi_cancel() >------------------------------------------------------*/
@@ -141,7 +137,9 @@ ncmpi_cancel(int  ncid,
     status = ncmpii_NC_check_id(ncid, &ncp);
     if (status != NC_NOERR) return status;
 
+    /* 1.7.0 and after nonblocking APIs can be called in define mode.
     if (NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_EINDEFINE)
+    */
 
     return ncmpii_cancel(ncp, num_req, req_ids, statuses);
 }
@@ -155,121 +153,167 @@ ncmpii_cancel(NC  *ncp,
               int *req_ids,  /* [num_req]: IN/OUT */
               int *statuses) /* [num_req] can be NULL (ignore status) */
 {
-    int i, j, status=NC_NOERR;
-    NC_req *pre_req, *cur_req, *next_req;
-
-    if (num_req == 0)
-        return NC_NOERR;
-
-    if (num_req == NC_REQ_ALL) {
-        /* cancel all pending requests, ignore req_ids and statuses */
-        cur_req = ncp->head;
-        while (cur_req != NULL) {
-            next_req = cur_req->next;
-            FREE_REQUEST(cur_req)
-            NCI_Free(cur_req);
-            cur_req = next_req;
-        }
-        ncp->head = NULL;
-        ncp->tail = NULL;
-        return NC_NOERR;
-    }
-    else if (num_req == NC_GET_REQ_ALL) {
-        /* cancel all pending get requests, ignore req_ids and statuses */
-        cur_req = ncp->head;
-        while (cur_req != NULL) {
-            next_req = cur_req->next;
-            if (cur_req->rw_flag == READ_REQ) {
-                if (cur_req == ncp->head)
-                    ncp->tail = ncp->head = next_req;
-                else
-                    ncp->tail->next = next_req;
-
-                FREE_REQUEST(cur_req)
-                NCI_Free(cur_req);
-            }
-            else { /* a put request */
-                ncp->tail = cur_req;
+    int i, j, first_non_null_get, first_non_null_put, status=NC_NOERR;
+
+    if (num_req == 0) return NC_NOERR;
+
+    if (num_req == NC_GET_REQ_ALL || num_req == NC_REQ_ALL) {
+        /* cancel all pending read requests, ignore req_ids and statuses */
+        for (i=0; i<ncp->numGetReqs; i++) {
+            if (ncp->get_list[i].num_recs > 0) {
+                if (ncp->get_list[i].imaptype != MPI_DATATYPE_NULL)
+                    MPI_Type_free(&ncp->get_list[i].imaptype);
+                if (!ncp->get_list[i].buftype_is_contig)
+                    MPI_Type_free(&ncp->get_list[i].buftype);
+                if (ncp->get_list[i].tmpBuf != NULL)
+                    MPI_Type_free(&ncp->get_list[i].buftype);
             }
-            cur_req = next_req;
+            FREE_REQUEST(ncp->get_list[i])
         }
-        return NC_NOERR;
-    }
-    else if (num_req == NC_PUT_REQ_ALL) {
-        /* cancel all pending put requests, ignore req_ids and statuses */
-        cur_req = ncp->head;
-        while (cur_req != NULL) {
-            next_req = cur_req->next;
-            if (cur_req->rw_flag == WRITE_REQ) {
-                if (cur_req == ncp->head)
-                    ncp->tail = ncp->head = next_req;
-                else
-                    ncp->tail->next = next_req;
-
-                FREE_REQUEST(cur_req)
-                NCI_Free(cur_req);
-            }
-            else { /* a get request */
-                ncp->tail = cur_req;
-            }
-            cur_req = next_req;
-        }
-        return NC_NOERR;
+        NCI_Free(ncp->get_list);
+        ncp->get_list = NULL;
+        ncp->numGetReqs = 0;
     }
 
-    /* collect the requests from the linked list */
-    for (i=0; i<num_req; i++) {
-        int found_id=-1;
-        if (statuses != NULL) statuses[i] = NC_NOERR;
+    if (num_req == NC_PUT_REQ_ALL || num_req == NC_REQ_ALL) {
+        /* cancel all pending write requests, ignore req_ids and statuses */
+        NC_req *put_list = ncp->put_list;
+        for (i=0; i<ncp->numPutReqs; i++) {
+            if (put_list[i].num_recs != 0 && put_list[i].need_swap_back_buf)
+                /* if user buffer is in-place byte-swapped, swap it back */
+                ncmpii_in_swapn(put_list[i].buf,
+                                put_list[i].bnelems * put_list[i].num_recs,
+                                ncmpix_len_nctype(put_list[i].varp->type));
 
-        if (req_ids[i] == NC_REQ_NULL)
-            continue;
+            if (put_list[i].tmpBuf != NULL && put_list[i].abuf_index == -1)
+                NCI_Free(put_list[i].tmpBuf);
 
-        if (ncp->head == NULL) {
-            if (statuses != NULL) DEBUG_ASSIGN_ERROR(statuses[i], NC_EINVAL_REQUEST)
-            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINVAL_REQUEST)
-            continue;
+            FREE_REQUEST(put_list[i])
         }
+        NCI_Free(put_list);
+        ncp->put_list = NULL;
+        ncp->numPutReqs = 0;
+        if (ncp->abuf != NULL) { /* clear out the attached buffer usage */
+            ncp->abuf->tail = 0;
+            ncp->abuf->size_used = 0;
+        }
+    }
+    if (num_req < 0) return NC_NOERR;
 
-        pre_req = cur_req = ncp->head;
-        while (cur_req != NULL) {
-            /* there may be more than one node with the same ID */
-            if (cur_req->id == req_ids[i]) {
-                if (cur_req == ncp->head) { /* move ncp->head ahead */
-                    ncp->head = cur_req->next;
-                    pre_req = ncp->head;
+    /* check each request ID from the read/write request list */
+    first_non_null_get = 0;
+    first_non_null_put = 0;
+    for (i=0; i<num_req; i++) {
+        if (statuses != NULL) statuses[i] = NC_NOERR;
+
+        if (req_ids[i] == NC_REQ_NULL) continue;
+
+        if (req_ids[i] & 1) {
+            /* check if this is a read request (id is an odd number) */
+            NC_req *get_list = ncp->get_list;
+            int last_index=-1;
+            for (j=first_non_null_get; j<ncp->numGetReqs; j++) {
+                if (get_list[j].id == NC_REQ_NULL) continue;
+                /* there may be more than one node with the same ID */
+                if (get_list[j].id == req_ids[i]) { /* found it */
+                    if (last_index < 0) last_index = j; /* keep first index */
+                    if (get_list[j].num_recs > 0) {
+                        if (get_list[j].imaptype != MPI_DATATYPE_NULL)
+                            MPI_Type_free(&get_list[j].imaptype);
+                        if (!get_list[j].buftype_is_contig)
+                            MPI_Type_free(&get_list[j].buftype);
+                        if (get_list[j].tmpBuf != NULL) {
+                            NCI_Free(get_list[j].tmpBuf);
+                            MPI_Type_free(&get_list[j].buftype);
+                        }
+                    }
+                    FREE_REQUEST(get_list[j])
+                    get_list[j].id = NC_REQ_NULL; /* marked as freed */
                 }
-                else /* move pre_req ahead */
-                    pre_req->next = cur_req->next;
-
-                FREE_REQUEST(cur_req)
-                NCI_Free(cur_req);
-                found_id = req_ids[i];
-                /* move cur_req ahead */
-                cur_req = (pre_req == ncp->head) ? pre_req : pre_req->next;
+                else if (last_index >= 0)
+                    break; /* done with all requests of this ID */
             }
-            else if (found_id >= 0) break;
-            else {
-                if (cur_req == pre_req) cur_req = pre_req->next;
-                else {
-                    pre_req = cur_req;
-                    cur_req = pre_req->next;
+            if (last_index >= 0) { /* found in read list */
+                /* using first_non_null_get only makes sense when the request
+                 * IDs in get_list[] are monotonically nondecreasing, which is
+                 * the case in PnetCDF
+                 */
+                if (last_index == first_non_null_get) first_non_null_get = j;
+                req_ids[i] = NC_REQ_NULL;
+                continue; /* loop i, go to next request ID */
+            }
+            /* else means req_ids[i] is not found in get_list[] */
+        }
+        else {
+            /* check if this is a write request (id is an even number) */
+            NC_req *put_list = ncp->put_list;
+            int last_index=-1;
+            for (j=first_non_null_put; j<ncp->numPutReqs; j++) {
+                if (put_list[j].id == NC_REQ_NULL) continue;
+                /* there may be more than one node with the same ID */
+                if (put_list[j].id == req_ids[i]) {
+                    if (last_index < 0) {
+                        last_index = j;
+                        /* put_list[j].num_recs should be >= 1 */
+                        if (put_list[j].need_swap_back_buf)
+                            /* if user buffer is in-place byte-swapped, swap it back */
+                            ncmpii_in_swapn(put_list[j].buf,
+                                   put_list[j].bnelems * put_list[j].num_recs,
+                                   ncmpix_len_nctype(put_list[j].varp->type));
+
+                        if (put_list[j].tmpBuf != NULL &&
+                            put_list[j].abuf_index == -1)
+                            NCI_Free(put_list[j].tmpBuf);
+                    }
+                    FREE_REQUEST(put_list[j])
+                    put_list[j].id = NC_REQ_NULL; /* marked as freed */
                 }
+                else if (last_index >= 0)
+                    break; /* done with all requests of this ID */
+            }
+            if (last_index >= 0) { /* found in write list */
+                /* using first_non_null_put only makes sense when the request
+                 * IDs in put_list[] are monotonically nondecreasing, which is
+                 * the case in PnetCDF
+                 */
+                if (last_index == first_non_null_put) first_non_null_put = j;
+                req_ids[i] = NC_REQ_NULL;
+                continue; /* loop i, go to next request ID */
             }
+            /* else means req_ids[i] is not found in put_list[] */
         }
+        /* no such request ID, if the program reached here */
+        if (statuses != NULL) DEBUG_ASSIGN_ERROR(statuses[i], NC_EINVAL_REQUEST)
+        /* retain the first error status */
+        if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINVAL_REQUEST)
+    }
+    if (ncp->abuf != NULL) ncmpii_abuf_coalesce(ncp);
 
-        if (found_id == -1) { /* no such request ID */
-            if (statuses != NULL) DEBUG_ASSIGN_ERROR(statuses[i], NC_EINVAL_REQUEST)
-            /* retain the first error status */
-            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINVAL_REQUEST)
-        }
-        else req_ids[i] = NC_REQ_NULL;
+    /* coalesce get_list */
+    for (i=0,j=first_non_null_get; j<ncp->numGetReqs; j++) {
+        for (; ncp->get_list[j].id==NC_REQ_NULL && j<ncp->numGetReqs; j++);
+        if (j == ncp->numGetReqs) break;
+        if (i < j) ncp->get_list[i] = ncp->get_list[j];
+        i++;
+    }
+    ncp->numGetReqs = i;
+    if (ncp->numGetReqs == 0) {
+        NCI_Free(ncp->get_list);
+        ncp->get_list = NULL;
     }
 
-    /* make sure ncp->tail pointing to the tail */
-    ncp->tail = ncp->head;
-    while (ncp->tail != NULL && ncp->tail->next != NULL)
-        ncp->tail = ncp->tail->next;
+    /* coalesce put_list */
+    for (i=0,j=first_non_null_put; j<ncp->numPutReqs; j++) {
+        for (; ncp->put_list[j].id==NC_REQ_NULL && j<ncp->numPutReqs; j++);
+        if (j == ncp->numPutReqs) break;
+        if (i < j) ncp->put_list[i] = ncp->put_list[j];
+        i++;
+    }
+    ncp->numPutReqs = i;
+    if (ncp->numPutReqs == 0) {
+        NCI_Free(ncp->put_list);
+        ncp->put_list = NULL;
+    }
 
     return status;
 }
@@ -279,44 +323,34 @@ int
 ncmpi_inq_nreqs(int  ncid,
                 int *nreqs) /* OUT: number of pending requests */
 {
-#ifdef OLD_METHOD
-    int     status, prev_id;
-    NC     *ncp;
-    NC_req *req_ptr;
+    int  i, status;
+    NC  *ncp;
 
     status = ncmpii_NC_check_id(ncid, &ncp);
     if (status != NC_NOERR) return status;
 
-/* TODO: add member num_reqs into NC_req to track this info */
-    req_ptr = ncp->head;
+    /* cannot just use *nreqs = ncp->numGetReqs + ncp->numPutReqs;
+     * because some request IDs are repeated, such as record variables and
+     * varn requests
+     */
     *nreqs = 0;
-    prev_id = NC_REQ_NULL;
-    while (req_ptr != NULL) {
-        /* some requests in the linked list may share the same ID, they were
-         * corresponding to the subrequests made from iput/iget/bput varn APIs.
-         */
-        if (req_ptr->id != prev_id) {
-            prev_id = req_ptr->id;
-            (*nreqs)++;
-        }
-        req_ptr = req_ptr->next;
+    for (i=0; i<ncp->numGetReqs; i++) {
+        if (i > 0 && ncp->get_list[i].id == ncp->get_list[i-1].id)
+            continue;
+        (*nreqs)++;
+    }
+    for (i=0; i<ncp->numPutReqs; i++) {
+        if (i > 0 && ncp->put_list[i].id == ncp->put_list[i-1].id)
+            continue;
+        (*nreqs)++;
     }
-#else
-    int  status;
-    NC  *ncp;
-
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
-
-    *nreqs = ncp->numGetReqs + ncp->numPutReqs;
-#endif
 
     return NC_NOERR;
 }
 
 #ifndef ENABLE_REQ_AGGREGATION
 /*----< extract_reqs() >-----------------------------------------------------*/
-/* based on the request type, construct the request ID arrays.
+/* based on the request type, construct an array of unique request IDs.
  * Input value of *num_reqs is NC_REQ_ALL, NC_GET_REQ_ALL, or NC_PUT_REQ_ALL
  * The output of *num_reqs is the number of requests.
  */
@@ -325,65 +359,56 @@ void extract_reqs(NC   *ncp,
                   int  *num_reqs, /* IN/OUT */
                   int **req_ids)  /* OUT */
 {
-    int req_type, prev_id = NC_REQ_NULL;
-    NC_req *req_ptr = ncp->head;
+    int i, req_type, prev_id;
 
     req_type = *num_reqs;
 
-    /* first while loop finds the number of requests to flush */
+    /* first loop finds the number of unique request IDs
+     * some requests may share the same ID, they were requests to record
+     * variables or called from iput/iget/bput varn APIs.
+     */
     *num_reqs = 0;
-    while (req_ptr != NULL) {
-        /* some requests in the linked list may share the same ID, they were
-         * corresponding to the subrequests made from iput/iget/bput varn APIs.
-         */
-        if (req_type == NC_REQ_ALL) {
-            if (req_ptr->id != prev_id) {
-                prev_id = req_ptr->id;
+    prev_id = -1;
+    if (req_type == NC_GET_REQ_ALL || req_type == NC_REQ_ALL) {
+        for (i=0; i<ncp->numGetReqs; i++) {
+            if (ncp->get_list[i].id != prev_id) {
+                prev_id = ncp->get_list[i].id;
                 (*num_reqs)++;
             }
         }
-        else if (req_type == NC_GET_REQ_ALL) {
-            if (req_ptr->rw_flag == READ_REQ && req_ptr->id != prev_id) {
-                prev_id = req_ptr->id;
-                (*num_reqs)++;
-            }
-        }
-        else if (req_type == NC_PUT_REQ_ALL) {
-            if (req_ptr->rw_flag == WRITE_REQ && req_ptr->id != prev_id) {
-                prev_id = req_ptr->id;
+    }
+    prev_id = -1;
+    if (req_type == NC_PUT_REQ_ALL || req_type == NC_REQ_ALL) {
+        for (i=0; i<ncp->numPutReqs; i++) {
+            if (ncp->put_list[i].id != prev_id) {
+                prev_id = ncp->put_list[i].id;
                 (*num_reqs)++;
             }
         }
-        req_ptr = req_ptr->next;
     }
 
     /* allocate ID array */
     (*req_ids) = (int*) NCI_Malloc(*num_reqs * sizeof(int));
 
-    /* second while loop fills the request IDs */
-    req_ptr = ncp->head;
+    /* second loop fills the request IDs */
     *num_reqs = 0;
-    prev_id = NC_REQ_NULL;
-    while (req_ptr != NULL) {
-        if (req_type == NC_REQ_ALL) {
-            if (req_ptr->id != prev_id) {
-                prev_id = req_ptr->id;
-                (*req_ids)[(*num_reqs)++] = prev_id;
-            }
-        }
-        else if (req_type == NC_GET_REQ_ALL) {
-            if (req_ptr->rw_flag == READ_REQ && req_ptr->id != prev_id) {
-                prev_id = req_ptr->id;
+    prev_id = -1;
+    if (req_type == NC_GET_REQ_ALL || req_type == NC_REQ_ALL) {
+        for (i=0; i<ncp->numGetReqs; i++) {
+            if (ncp->get_list[i].id != prev_id) {
+                prev_id = ncp->get_list[i].id;
                 (*req_ids)[(*num_reqs)++] = prev_id;
             }
         }
-        else if (req_type == NC_PUT_REQ_ALL) {
-            if (req_ptr->rw_flag == WRITE_REQ && req_ptr->id != prev_id) {
-                prev_id = req_ptr->id;
+    }
+    prev_id = -1;
+    if (req_type == NC_PUT_REQ_ALL || req_type == NC_REQ_ALL) {
+        for (i=0; i<ncp->numPutReqs; i++) {
+            if (ncp->put_list[i].id != prev_id) {
+                prev_id = ncp->put_list[i].id;
                 (*req_ids)[(*num_reqs)++] = prev_id;
             }
         }
-        req_ptr = req_ptr->next;
     }
 }
 #endif
@@ -400,8 +425,8 @@ void extract_reqs(NC   *ncp,
  * nonblocking requests.
  */
 int
-ncmpi_wait(int ncid,
-           int num_reqs,
+ncmpi_wait(int  ncid,
+           int  num_reqs,
            int *req_ids,  /* [num_reqs]: IN/OUT */
            int *statuses) /* [num_reqs] */
 {
@@ -744,11 +769,11 @@ ncmpii_wait(NC  *ncp,
 {
     int i, j, err=NC_NOERR, status=NC_NOERR;
     int do_read, do_write, num_w_reqs=0, num_r_reqs=0;
-    NC_req *pre_req, *cur_req, *next_req;
-    NC_req *w_req_head=NULL, *w_req_tail=NULL;
-    NC_req *r_req_head=NULL, *r_req_tail=NULL;
+    int first_non_null_get, first_non_null_put;
+    MPI_Offset newnumrecs=0;
+    NC_req *put_list=NULL, *get_list=NULL;
 
-    if (NC_indef(ncp)) { /* This API can only be called in data mode */
+    if (NC_indef(ncp)) { /* wait must be called in data mode */
         DEBUG_ASSIGN_ERROR(err, NC_EINDEFINE)
         goto err_check;
     }
@@ -756,250 +781,160 @@ ncmpii_wait(NC  *ncp,
     /* check the MPI file handles for collective or independent mode */
     if (io_method == INDEP_IO)
         err = ncmpii_check_mpifh(ncp, 0);
-    else if (io_method == COLL_IO)
+    else /* if (io_method == COLL_IO) */
         err = ncmpii_check_mpifh(ncp, 1);
     if (err != NC_NOERR) goto err_check;
 
-    if (num_reqs == NC_REQ_ALL) { /* flush all pending requests */
+    num_r_reqs = 0;
+    num_w_reqs = 0;
+    if (num_reqs == NC_GET_REQ_ALL || num_reqs == NC_REQ_ALL) {
         /* in this case, arguments req_ids[] and statuses[] are ignored */
-        cur_req = ncp->head;
-        while (cur_req != NULL) {
-            cur_req->status = NULL;
-            next_req = cur_req->next;
-            if (cur_req->rw_flag == READ_REQ) {
-                /* add cur_req to r_req_tail */
-                if (r_req_head == NULL) {
-                    r_req_head = cur_req;
-                    r_req_tail = cur_req;
-                }
-                else {
-                    r_req_tail->next = cur_req;
-                    r_req_tail = r_req_tail->next;
-                }
-                r_req_tail->next = NULL;
-                num_r_reqs += (cur_req->num_subreqs == 0) ?
-                              1 : cur_req->num_subreqs;
-                /* if this request is to a record variable, then count all
-                 * its subrequests (one for each individual record) */
-            }
-            else { /* add cur_req to w_req_tail */
-                if (w_req_head == NULL) {
-                    w_req_head = cur_req;
-                    w_req_tail = cur_req;
-                }
-                else {
-                    w_req_tail->next = cur_req;
-                    w_req_tail = w_req_tail->next;
-                }
-                w_req_tail->next = NULL;
-                num_w_reqs += (cur_req->num_subreqs == 0) ?
-                              1 : cur_req->num_subreqs;
-                /* if this request is to a record variable, then count all
-                 * its subrequests (one for each individual record) */
-            }
-            cur_req = next_req;
-        }
-        ncp->head       = NULL;
-        ncp->tail       = NULL;
+        num_r_reqs      = ncp->numGetReqs;
+        get_list        = ncp->get_list;
         ncp->numGetReqs = 0;
-        ncp->numPutReqs = 0;
-        num_reqs        = 0; /* to skip the loop below */
+        ncp->get_list   = NULL;
     }
-    else if (num_reqs == NC_GET_REQ_ALL) { /* flush all pending get requests */
+    if (num_reqs == NC_PUT_REQ_ALL || num_reqs == NC_REQ_ALL) {
         /* in this case, arguments req_ids[] and statuses[] are ignored */
-        cur_req = ncp->head;
-        while (cur_req != NULL) {
-            next_req = cur_req->next;
-            if (cur_req->rw_flag == READ_REQ) {
-                cur_req->status = NULL; /* ignore status */
-                if (cur_req == ncp->head)
-                    ncp->tail = ncp->head = next_req;
-                else
-                    ncp->tail->next = next_req;
-
-                /* add cur_req to r_req_tail */
-                if (r_req_head == NULL) {
-                    r_req_head = cur_req;
-                    r_req_tail = cur_req;
-                }
-                else {
-                    r_req_tail->next = cur_req;
-                    r_req_tail = r_req_tail->next;
-                }
-                r_req_tail->next = NULL;
-                num_r_reqs += (cur_req->num_subreqs == 0) ?
-                              1 : cur_req->num_subreqs;
-                /* if this request is to a record variable, then count all
-                 * its subrequests (one for each individual record) */
-            }
-            else { /* a put request */
-                ncp->tail = cur_req;
-            }
-            cur_req = next_req;
-        }
-        ncp->numGetReqs = 0;
-        num_reqs = 0; /* to skip the loop below */
-    }
-    else if (num_reqs == NC_PUT_REQ_ALL) { /* flush all pending put requests */
-        /* in this case, arguments req_ids[] and statuses[] are ignored */
-        cur_req = ncp->head;
-        while (cur_req != NULL) {
-            next_req = cur_req->next;
-            if (cur_req->rw_flag == WRITE_REQ) {
-                cur_req->status = NULL; /* ignore status */
-                if (cur_req == ncp->head)
-                    ncp->tail = ncp->head = next_req;
-                else
-                    ncp->tail->next = next_req;
-
-                /* add cur_req to w_req_tail */
-                if (w_req_head == NULL) {
-                    w_req_head = cur_req;
-                    w_req_tail = cur_req;
-                }
-                else {
-                    w_req_tail->next = cur_req;
-                    w_req_tail = w_req_tail->next;
-                }
-                w_req_tail->next = NULL;
-                num_w_reqs += (cur_req->num_subreqs == 0) ?
-                              1 : cur_req->num_subreqs;
-                /* if this request is to a record variable, then count all
-                 * its subrequests (one for each individual record) */
-            }
-            else { /* a put request */
-                ncp->tail = cur_req;
-            }
-            cur_req = next_req;
-        }
+        num_w_reqs      = ncp->numPutReqs;
+        put_list        = ncp->put_list;
         ncp->numPutReqs = 0;
-        num_reqs = 0; /* to skip the loop below */
+        ncp->put_list   = NULL;
     }
-    /* extract the matched requests from the pending queue (a linked list
-     * containing all nonblocking requests posted by far) into two separate
-     * linked lists for read and write. In the meantime coalesce the pending
-     * request queue.
+
+    /* extract the matched requests from the pending queues (get_list and
+     * put_list containing all nonblocking requests posted by far) into two
+     * separate arrays to be used for read and write separately. In the
+     * meantime, coalesce the pending request lists.
      */
-    for (i=0; i<num_reqs; i++) {
-        int found_id=-1;
+    if (num_reqs > 0) { /* assume the max number of requests */
+        put_list = (NC_req*) NCI_Malloc((size_t)ncp->numPutReqs*sizeof(NC_req));
+        get_list = (NC_req*) NCI_Malloc((size_t)ncp->numGetReqs*sizeof(NC_req));
+    }
 
-        if (statuses != NULL)
-            statuses[i] = NC_NOERR; /* initialize the request's status */
+    /* check each request ID from the read/write request list */
+    first_non_null_get = 0;
+    first_non_null_put = 0;
+    for (i=0; i<num_reqs; i++) {
+        /* initialize the request's status */
+        if (statuses != NULL) statuses[i] = NC_NOERR;
 
         if (req_ids[i] == NC_REQ_NULL) continue; /* skip NULL request */
 
-        if (ncp->head == NULL) {
-            /* no more pending requests in the queue, this request is invalid */
-            if (statuses != NULL) DEBUG_ASSIGN_ERROR(statuses[i], NC_EINVAL_REQUEST)
-            /* retain the first error status */
-            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINVAL_REQUEST)
-            continue;
-            /* don't break loop i, continue to set the error status */
-        }
-
-        /* find req_ids[i] from the pending queue */
-        pre_req = cur_req = ncp->head;
-        while (cur_req != NULL) {
-            /* there may be more than one pending request with the same ID.
-             * In this case, these requests are from a single nonblocking
-             * varn API.
-             */
-            if (cur_req->id == req_ids[i]) { /* found it */
-                /* point status of this request to user's statuses[i] */
-                if (statuses != NULL)
-                    cur_req->status = statuses + i;
-                else
-                    cur_req->status = NULL;
-                /* point all subrequests' statuses to status */
-                for (j=0; j<cur_req->num_subreqs; j++)
-                    cur_req->subreqs[j].status = cur_req->status;
-
-                /* remove cur_req from the ncp->head linked list */
-                if (cur_req == ncp->head) { /* move cur_req to next */
-                    ncp->head = cur_req->next;
-                    pre_req = ncp->head;
-                }
-                else /* move pre_req and cur_req to next */
-                    pre_req->next = cur_req->next;
-
-                next_req = cur_req->next;
-
-                if (cur_req->rw_flag == READ_REQ) {
-                    if (found_id == -1) ncp->numGetReqs--;
-
-                    /* add cur_req to r_req_tail */
-                    if (r_req_head == NULL) {
-                        r_req_head = cur_req;
-                        r_req_tail = cur_req;
-                    }
-                    else {
-                        r_req_tail->next = cur_req;
-                        r_req_tail = r_req_tail->next;
-                    }
-                    r_req_tail->next = NULL;
-                    num_r_reqs += (cur_req->num_subreqs == 0) ?
-                                  1 : cur_req->num_subreqs;
-                    /* if this request is to a record variable, then count all
-                     * its subrequests (one for each individual record) */
-                }
-                else { /* add cur_req to w_req_tail */
-                    if (found_id == -1) ncp->numPutReqs--;
-
-                    if (w_req_head == NULL) {
-                        w_req_head = cur_req;
-                        w_req_tail = cur_req;
-                    }
-                    else {
-                        w_req_tail->next = cur_req;
-                        w_req_tail = w_req_tail->next;
-                    }
-                    w_req_tail->next = NULL;
-                    num_w_reqs += (cur_req->num_subreqs == 0) ?
-                                  1 : cur_req->num_subreqs;
-                    /* if this request is to a record variable, then count all
-                     * its subrequests (one for each individual record) */
+        if (req_ids[i] & 1) {
+            /* check if this is a read request (id is an odd number)*/
+            int last_index=-1;
+            for (j=first_non_null_get; j<ncp->numGetReqs; j++) {
+                if (ncp->get_list[j].id == NC_REQ_NULL) continue;
+                /* there may be more than one node with the same ID */
+                if (ncp->get_list[j].id == req_ids[i]) { /* found it */
+                    if (last_index < 0) last_index = j; /* keep first index */
+                    get_list[num_r_reqs] = ncp->get_list[j];
+                    get_list[num_r_reqs].status = (statuses == NULL) ? NULL :
+                                                  statuses + i;
+                    num_r_reqs++;
+                    ncp->get_list[j].id = NC_REQ_NULL; /* marked as freed */
                 }
-                found_id = req_ids[i]; /* indicating previous found ID */
-                cur_req = next_req;
+                else if (last_index >= 0)
+                    break; /* done with all requests of this ID */
             }
-            else if (found_id >= 0) {
-                /* same request IDs (for varn APIs) are stored contiguously in
-                 * the linked list so if it is already found and this next
-                 * request has a different ID, no need to continue checking
-                 * the rest list */
-                break; /* while loop */
+            if (last_index >= 0) { /* found in read list */
+                /* using first_non_null_get only makes sense when the request
+                 * IDs in get_list[] are monotonically nondecreasing, which is
+                 * the case in PnetCDF
+                 */
+                if (last_index == first_non_null_get) first_non_null_get = j;
+                req_ids[i] = NC_REQ_NULL;
+                continue; /* loop i, go to next request ID */
             }
-            else { /* not found: move on to next pending request in the queue */
-                if (cur_req == pre_req) cur_req = pre_req->next;
-                else {
-                    pre_req = cur_req;
-                    cur_req = pre_req->next;
+        }
+        else { /* check if this is a write request (id is an even number) */
+            int last_index=-1;
+            for (j=first_non_null_put; j<ncp->numPutReqs; j++) {
+                if (ncp->put_list[j].id == NC_REQ_NULL) continue;
+                /* there may be more than one node with the same ID */
+                if (ncp->put_list[j].id == req_ids[i]) {
+                    if (last_index < 0) last_index = j;
+                    put_list[num_w_reqs] = ncp->put_list[j];
+                    put_list[num_w_reqs].status = (statuses == NULL) ? NULL :
+                                                  statuses + i;
+                    num_w_reqs++;
+                    ncp->put_list[j].id = NC_REQ_NULL; /* marked as freed */
                 }
+                else if (last_index >= 0)
+                    break; /* done with all requests of this ID */
+            }
+            if (last_index >= 0) { /* found in write list */
+                /* using first_non_null_put only makes sense when the request
+                 * IDs in put_list[] are monotonically nondecreasing, which is
+                 * the case in PnetCDF
+                 */
+                if (last_index == first_non_null_put) first_non_null_put = j;
+                req_ids[i] = NC_REQ_NULL;
+                continue; /* loop i, go to next request ID */
             }
-        } /* done with searching the entire linked list for this request ID */
+        }
+        /* no such request ID, if the program reached here */
+        if (statuses != NULL) DEBUG_ASSIGN_ERROR(statuses[i], NC_EINVAL_REQUEST)
+        /* retain the first error status */
+        if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINVAL_REQUEST)
+    }
 
-        if (found_id == -1) { /* no such request ID */
-            if (statuses != NULL) DEBUG_ASSIGN_ERROR(statuses[i], NC_EINVAL_REQUEST)
-            if (status == NC_NOERR) /* retain the first error status */
-                DEBUG_ASSIGN_ERROR(status, NC_EINVAL_REQUEST)
+    if (num_reqs > 0) { /* not NC_REQ_ALL, NC_GET_REQ_ALL, or NC_PUT_REQ_ALL */
+        /* coalesce get_list */
+        for (i=0,j=first_non_null_get; j<ncp->numGetReqs; j++) {
+            for (; ncp->get_list[j].id==NC_REQ_NULL && j<ncp->numGetReqs; j++);
+            if (j == ncp->numGetReqs) break;
+            if (i < j) ncp->get_list[i] = ncp->get_list[j];
+            i++;
         }
-        else req_ids[i] = NC_REQ_NULL;
+        ncp->numGetReqs = i;
+        if (ncp->numGetReqs == 0) {
+            NCI_Free(ncp->get_list);
+            ncp->get_list = NULL;
+        }
+
+        /* coalesce put_list */
+        for (i=0,j=first_non_null_put; j<ncp->numPutReqs; j++) {
+            for (; ncp->put_list[j].id==NC_REQ_NULL && j<ncp->numPutReqs; j++);
+            if (j == ncp->numPutReqs) break;
+            if (i < j) ncp->put_list[i] = ncp->put_list[j];
+            i++;
+        }
+        ncp->numPutReqs = i;
+        if (ncp->numPutReqs == 0) { /* free put_list */
+            NCI_Free(ncp->put_list);
+            ncp->put_list = NULL;
+        }
+
+        if (num_w_reqs == 0) NCI_Free(put_list);
+        if (num_r_reqs == 0) NCI_Free(get_list);
     }
-    if (num_reqs > 0) {
-        /* make sure ncp->tail pointing to the tail of the pending request queue */
-        ncp->tail = ncp->head;
-        while (ncp->tail != NULL && ncp->tail->next != NULL)
-            ncp->tail = ncp->tail->next;
+
+    /* calculate new number of records:
+     * Need to update the number of records if new records have been created.
+     * For nonblocking APIs, there is no way for a process to know whether
+     * others write to a record variable or not. Hence, we must sync the
+     * number of records for write request.
+     * Because netCDF allows only one unlimited dimension, find the
+     * maximum number of records from all nonblocking write requests
+     */
+    newnumrecs = ncp->numrecs;
+    for (i=0; i<num_w_reqs; i++) {
+        if (!IS_RECVAR(put_list[i].varp)) continue; /* not a record var */
+        if (put_list[i].bnelems == 0) continue; /* 0-len or invalid request */
+        newnumrecs = MAX(newnumrecs, put_list[i].start[0] + put_list[i].count[0]);
     }
 
 err_check:
     if (io_method == COLL_IO) {
         int mpireturn;
-        int io_req[3], do_io[3];  /* [0]: read [1]: write [2]: error */
+        MPI_Offset io_req[4], do_io[4];  /* [0]: read [1]: write [2]: error */
         io_req[0] = num_r_reqs;
         io_req[1] = num_w_reqs;
         io_req[2] = -err;   /* all NC errors are negative */
-        TRACE_COMM(MPI_Allreduce)(io_req, do_io, 3, MPI_INT, MPI_MAX,
+        io_req[3] = newnumrecs;
+        TRACE_COMM(MPI_Allreduce)(io_req, do_io, 4, MPI_OFFSET, MPI_MAX,
                                   ncp->nciop->comm);
         if (mpireturn != MPI_SUCCESS)
  	    return ncmpii_handle_error(mpireturn, "MPI_Allreduce"); 
@@ -1009,8 +944,9 @@ err_check:
 
         /* if at least one process has a non-zero request, all processes must
          * participate the collective read/write */
-        do_read  = do_io[0];
-        do_write = do_io[1];
+        do_read    = (int)do_io[0];
+        do_write   = (int)do_io[1];
+        newnumrecs = do_io[3];
     }
     else {
         if (err != NC_NOERR) return err;
@@ -1020,12 +956,12 @@ err_check:
 
     /* carry out writes and reads separately (writes first) */
     if (do_write > 0)
-        err = ncmpii_wait_getput(ncp, num_w_reqs, w_req_head, WRITE_REQ,
-                                 io_method);
+        err = ncmpii_wait_getput(ncp, num_w_reqs, put_list, WRITE_REQ,
+                                 io_method, newnumrecs);
 
     if (do_read > 0)
-        err = ncmpii_wait_getput(ncp, num_r_reqs, r_req_head, READ_REQ,
-                                 io_method);
+        err = ncmpii_wait_getput(ncp, num_r_reqs, get_list, READ_REQ,
+                                 io_method, newnumrecs);
 
     /* retain the first error status */
     if (status == NC_NOERR) status = err;
@@ -1036,158 +972,155 @@ err_check:
      * unpack/byte-swap/type-convert a temp buffer to the user read buf
      */
 
-    if (w_req_head != NULL) {
-        cur_req = w_req_head;
-        while (cur_req != NULL) {
-            /* must byte-swap the user buffer back to its original Endianness
-               only when the buffer itself has been byte-swapped before,
-               i.e. NOT buftype_is_contig && NOT ncmpii_need_convert() &&
-               ncmpii_need_swap()
-             */
-            if (cur_req->need_swap_back_buf)
-                ncmpii_in_swapn(cur_req->buf, cur_req->bnelems,
-                                ncmpix_len_nctype(cur_req->varp->type));
-            cur_req = cur_req->next;
-        }
-        cur_req = w_req_head;
-        while (cur_req != NULL) {
-            /* free temp space allocated for iput/bput varn requests. Note that
-             * tmpBuf is used only by nonblocking varn APIs. This while loop
-             * is not combined with the one above because the nonblocking varn
-             * APIs may be used. During the posting of a nonblocking varn
-             * request, the temporary buffer, if allocated, can be divided into
-             * several sub-buffers, each used in a separate requests. Only the
-             * first subrequest's tmpBuf will be set to non-NULL, indicating
-             * it should be freed.
-             */
-            if (cur_req->tmpBuf != NULL && cur_req->abuf_index == -1)
-                NCI_Free(cur_req->tmpBuf);
+    for (i=0; i<num_w_reqs; i++) {
+        /* must byte-swap the user buffer back to its original Endianness
+         * only when the buffer itself has been byte-swapped before,
+         * i.e. NOT buftype_is_contig && NOT ncmpii_need_convert() &&
+         * ncmpii_need_swap()
+         * Only the lead record (or the fix-size request) does this
+         */
+        if (put_list[i].num_recs > 0 && put_list[i].need_swap_back_buf)
+            ncmpii_in_swapn(put_list[i].buf,
+                            put_list[i].bnelems * put_list[i].num_recs,
+                            ncmpix_len_nctype(put_list[i].varp->type));
+    }
+    for (i=0; i<num_w_reqs; i++) {
+        /* free space allocated for the request objects
+         * tmpBuf is used only by nonblocking varn APIs. During the posting of
+         * a nonblocking varn request, the temporary buffer, if allocated, can
+         * be divided into several sub-buffers, each used in a separate
+         * requests. If a request's tmpBuf is set to non-NULL, indicating it
+         * should be freed. Because put_list[] may be sorted based on
+         * offset_start, non-NULL tmpBuf can be in any put_list[], this loop
+         * cannot be combined with the above one. We need to go through
+         * put_list[] to check each one for non-NULL tmpBuf.
+         */
+        if (put_list[i].tmpBuf != NULL && put_list[i].abuf_index == -1)
+            NCI_Free(put_list[i].tmpBuf);
 
-            FREE_REQUEST(cur_req)
-            pre_req = cur_req;
-            cur_req = cur_req->next;
-            NCI_Free(pre_req);
-        }
+        FREE_REQUEST(put_list[i])
+    }
+    if (num_w_reqs > 0) {
         /* once the bput requests are served, we reclaim the space and try
          * coalesce the freed space for the attached buffer */
         if (ncp->abuf != NULL) ncmpii_abuf_coalesce(ncp);
+        NCI_Free(put_list);
     }
 
-    if (r_req_head != NULL) {
-        cur_req = r_req_head;
-        while (cur_req != NULL) {
-            NC_var *varp = cur_req->varp;
+    for (i=0; i<num_r_reqs; i++) {
+        void *cbuf, *lbuf;
+        int el_size, position;
+        MPI_Offset insize, bnelems;
+        NC_var *varp;
 
-            /* now, xbuf contains the data read from the file.
-             * It needs to be type-converted + byte-swapped to cbuf
-             */
-            void *cbuf, *lbuf;
-            int el_size, position;
-            MPI_Offset insize;
+        /* non-lead record requests skip type-conversion/byte-swap/unpack */
+        if (get_list[i].num_recs == 0) continue;
 
-            MPI_Type_size(cur_req->ptype, &el_size);
-            insize = cur_req->bnelems * el_size;
-            if (insize != (int)insize && status == NC_NOERR)
-                DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
-
-            if (ncmpii_need_convert(varp->type, cur_req->ptype)) {
-                /* need type conversion from the external type to user buffer
-                   type */
-                if (cur_req->imaptype != MPI_DATATYPE_NULL ||
-                    !cur_req->buftype_is_contig)
-                    cbuf = NCI_Malloc((size_t)insize);
-                else
-                    cbuf = cur_req->buf;
-
-                /* type convert + byte swap from xbuf to cbuf */
-                DATATYPE_GET_CONVERT(varp->type, cur_req->xbuf, cbuf,
-                                     cur_req->bnelems, cur_req->ptype, err)
-                /* keep the first error */
-                if (cur_req->status != NULL && *cur_req->status == NC_NOERR)
-                    *cur_req->status = err;
-                if (status == NC_NOERR) status = err;
-            } else {
-                if (ncmpii_need_swap(varp->type, cur_req->ptype))
-                    ncmpii_in_swapn(cur_req->xbuf, cur_req->bnelems,
-                                    ncmpix_len_nctype(varp->type));
-                cbuf = cur_req->xbuf;
-            }
-
-            if (cur_req->imaptype != MPI_DATATYPE_NULL) {
-                /* handle the case for a true get_varm */
-                if (cur_req->buftype_is_contig)
-                    lbuf = cur_req->buf;
-                else
-                    lbuf = NCI_Malloc((size_t)insize);
-
-                /* unpack cbuf to lbuf based on imaptype */
-                position = 0;
-                MPI_Unpack(cbuf, (int)insize, &position, lbuf, 1,
-                           cur_req->imaptype, MPI_COMM_SELF);
-                MPI_Type_free(&cur_req->imaptype);
-
-                /* cbuf is no longer needed
-                 * for a true varm call, cbuf cannot be == cur_req->buf */
-                if (cbuf != cur_req->xbuf) NCI_Free(cbuf);
-                cbuf = NULL;
-            } else { /* get_vars */
-                lbuf = cbuf;
-            }
-
-            if (!cur_req->buftype_is_contig) {
-                /* unpack lbuf to buf based on buftype */
-                position = 0;
-                if (cur_req->bufcount != (int)cur_req->bufcount &&
-                    status == NC_NOERR)
-                    DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
-                MPI_Unpack(lbuf, (int)insize, &position, cur_req->buf,
-                           (int)cur_req->bufcount, cur_req->buftype,
-                           MPI_COMM_SELF);
-                MPI_Type_free(&cur_req->buftype);
-            }
-            /* lbuf is no longer needed */
-            if (lbuf != cur_req->buf && lbuf != cur_req->xbuf)
-                NCI_Free(lbuf);
+        /* now, xbuf contains the data read from the file.
+         * It needs to be type-converted + byte-swapped to cbuf
+         */
+        varp = get_list[i].varp;
+        MPI_Type_size(get_list[i].ptype, &el_size);
+        bnelems = get_list[i].bnelems * get_list[i].num_recs;
+        insize = bnelems * el_size;
+        if (insize != (int)insize && status == NC_NOERR)
+            DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
 
-            cur_req = cur_req->next;
-        }
+        if (ncmpii_need_convert(ncp->format, varp->type, get_list[i].ptype)) {
+            /* need type conversion from the external type to user buffer
+               type */
+            if (get_list[i].imaptype != MPI_DATATYPE_NULL ||
+                !get_list[i].buftype_is_contig)
+                cbuf = NCI_Malloc((size_t)insize);
+            else
+                cbuf = get_list[i].buf;
+
+            /* type convert + byte swap from xbuf to cbuf */
+            DATATYPE_GET_CONVERT(ncp->format, varp->type, get_list[i].xbuf,
+                                 cbuf, bnelems, get_list[i].ptype, err)
+
+            /* keep the first error */
+            if (get_list[i].status != NULL && *get_list[i].status == NC_NOERR)
+                *get_list[i].status = err;
+            if (status == NC_NOERR) status = err;
+        } else {
+            if (ncmpii_need_swap(varp->type, get_list[i].ptype))
+                ncmpii_in_swapn(get_list[i].xbuf, bnelems,
+                                ncmpix_len_nctype(varp->type));
+            cbuf = get_list[i].xbuf;
+        }
+
+        if (get_list[i].imaptype != MPI_DATATYPE_NULL) {
+            /* handle the case for a true get_varm */
+            if (get_list[i].buftype_is_contig)
+                lbuf = get_list[i].buf;
+            else
+                lbuf = NCI_Malloc((size_t)insize);
+
+            /* unpack cbuf to lbuf based on imaptype */
+            position = 0;
+            MPI_Unpack(cbuf, (int)insize, &position, lbuf, 1,
+                       get_list[i].imaptype, MPI_COMM_SELF);
+            MPI_Type_free(&get_list[i].imaptype);
+
+            /* cbuf is no longer needed
+             * for a true varm call, cbuf cannot be == get_list[i].buf */
+            if (cbuf != get_list[i].xbuf) NCI_Free(cbuf);
+            cbuf = NULL;
+        } else { /* get_vars */
+            lbuf = cbuf;
+        }
+
+        if (!get_list[i].buftype_is_contig) {
+            /* unpack lbuf to buf based on buftype */
+            position = 0;
+            if (get_list[i].bufcount != (int)get_list[i].bufcount &&
+                status == NC_NOERR)
+                DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+            MPI_Unpack(lbuf, (int)insize, &position, get_list[i].buf,
+                       (int)get_list[i].bufcount, get_list[i].buftype,
+                       MPI_COMM_SELF);
+            MPI_Type_free(&get_list[i].buftype);
+        }
+        /* lbuf is no longer needed */
+        if (lbuf != get_list[i].buf && lbuf != get_list[i].xbuf)
+            NCI_Free(lbuf);
+    }
+
+    for (i=0; i<num_r_reqs; i++) {
+        /* free space allocated for the request objects
+         * tmpBuf is used only by nonblocking varn APIs. During the posting of
+         * a nonblocking varn request, the temporary buffer, if allocated, can
+         * be divided into several sub-buffers, each used in a separate
+         * requests. If a request's tmpBuf is set to non-NULL, indicating it
+         * should be freed. Because get_list[] may be sorted based on
+         * offset_start, non-NULL tmpBuf can be in any get_list[], this loop
+         * cannot be combined with the above one. We need to go through
+         * get_list[] to check each one for  non-NULL tmpBuf.
+         */
+        if (get_list[i].tmpBuf != NULL) {
+            int position=0, bufsize;
+            MPI_Offset insize;
 
-        cur_req = r_req_head;
-        while (cur_req != NULL) {
-            /* free space allocated for the request objects
-             * tmpBuf is used only by nonblocking varn APIs. This while loop
-             * is not combined with the one above because the nonblocking varn
-             * APIs may be used. During the posting of a nonblocking varn
-             * request, the temporary buffer, if allocated, can be divided into
-             * several sub-buffers, each used in a separate requests. Only the
-             * first subrequest's tmpBuf will be set to non-NULL, indicating
-             * it should be freed.
+            /* unpack tmpBuf to userBuf and free tmpBuf
+             * Note this unpack must wait for all above unpacks are done
+             * because get_list[i].buf may be part of get_list[i].userBuf
              */
-            if (cur_req->tmpBuf != NULL) {
-                int position=0, bufsize;
-                MPI_Offset insize;
+            MPI_Type_size(get_list[i].buftype, &bufsize);
+            insize = get_list[i].bufcount * bufsize;
+            if (insize != (int)insize && status == NC_NOERR)
+                DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
 
-                /* unpack tmpBuf to userBuf and free tmpBuf
-                 * Note this unpack must wait for all above unpacks are done
-                 * because cur_req->buf may be part of cur_req->userBuf
-                 */
-                MPI_Type_size(cur_req->buftype, &bufsize);
-                insize = cur_req->bufcount * bufsize;
-                if (insize != (int)insize && status == NC_NOERR)
-                    DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
-
-                MPI_Unpack(cur_req->tmpBuf, (int)insize, &position,
-                           cur_req->userBuf, (int)cur_req->bufcount,
-                           cur_req->buftype, MPI_COMM_SELF);
-                NCI_Free(cur_req->tmpBuf);
-                MPI_Type_free(&cur_req->buftype);
-            }
-            FREE_REQUEST(cur_req)
-            pre_req = cur_req;
-            cur_req = cur_req->next;
-            NCI_Free(pre_req);
+            MPI_Unpack(get_list[i].tmpBuf, (int)insize, &position,
+                       get_list[i].userBuf, (int)get_list[i].bufcount,
+                       get_list[i].buftype, MPI_COMM_SELF);
+            NCI_Free(get_list[i].tmpBuf);
+            MPI_Type_free(&get_list[i].buftype);
         }
+        FREE_REQUEST(get_list[i])
     }
+    if (num_r_reqs > 0) NCI_Free(get_list);
+
     return status;
 }
 
@@ -1606,8 +1539,14 @@ ncmpii_req_aggregation(NC     *ncp,
                        int     io_method,   /* COLL_IO or INDEP_IO */
                        int     interleaved) /* interleaved in reqs[] */
 {
-    int i, type, err, status=NC_NOERR, ngroups;
-    int *group_index, *group_type;
+    int i, type, err, status=NC_NOERR, ngroups, mpireturn, buf_len;
+    int *group_index, *group_type, buf_type_size=0;
+    int *f_blocklengths, *b_blocklengths;
+    void *buf; /* point to starting buffer, used by MPI-IO call */
+    MPI_Aint      b_begin, b_addr, *f_disps, *b_disps;
+    MPI_Datatype  filetype, buf_type, *ftypes, *btypes;
+    MPI_File fh;
+    MPI_Status mpistatus;
 
     if (num_reqs == 0) { /* only COLL_IO can reach here for 0 request */
         assert(io_method == COLL_IO);
@@ -1628,7 +1567,7 @@ ncmpii_req_aggregation(NC     *ncp,
      * This approach is because MPI collective I/O requires each process's
      * fileview must contain only monotonic non-decreasing file offsets. Thus
      * if the nonblocking requests interleave with each other (although not
-     * overlapp), then we cannot simply concatenate the filetypes of individual
+     * overlap), then we cannot simply concatenate the filetypes of individual
      * requests. This approach flattens the requests of "interleaved" groups
      * into offset-length pairs, sorts, and merges them into an aggregated
      * filetype. Similar for building an aggregated I/O buffer type.
@@ -1690,11 +1629,6 @@ ncmpii_req_aggregation(NC     *ncp,
      * Then use one collective I/O to commit.
      */
 
-    void         *buf; /* point to starting buffer, used by MPI-IO call */
-    int          *f_blocklengths, *b_blocklengths;
-    MPI_Aint      b_begin, b_addr, *f_disps, *b_disps;
-    MPI_Datatype  filetype, buf_type, *ftypes, *btypes;
-
     ftypes = (MPI_Datatype*) NCI_Malloc((size_t)ngroups*2*sizeof(MPI_Datatype));
     btypes = ftypes + ngroups;
     f_blocklengths = (int*) NCI_Malloc((size_t)ngroups*2*SIZEOF_INT);
@@ -1806,7 +1740,7 @@ ncmpii_req_aggregation(NC     *ncp,
     NCI_Free(group_index);
     NCI_Free(group_type);
 
-    int mpireturn, buf_len=1;
+    buf_len=1;
 
     if (ngroups == 1) {
         /* use ftypes[0] and btypes[0] directly */
@@ -1861,8 +1795,7 @@ ncmpii_req_aggregation(NC     *ncp,
         }
     }
 
-    MPI_File fh;
-    MPI_Status mpistatus;
+    MPI_Type_size(buf_type, &buf_type_size);
 
     if (io_method == COLL_IO)
         fh = ncp->nciop->collective_fh;
@@ -1889,6 +1822,9 @@ ncmpii_req_aggregation(NC     *ncp,
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
+            else {
+                ncp->nciop->get_size += buf_len * buf_type_size;
+            }
         } else {
             TRACE_IO(MPI_File_read_at)(fh, offset, buf, buf_len, buf_type,
                                        &mpistatus);
@@ -1900,11 +1836,9 @@ ncmpii_req_aggregation(NC     *ncp,
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
-        }
-        if (mpireturn == MPI_SUCCESS) {
-            int get_size;
-            MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
-            ncp->nciop->get_size += get_size;
+            else {
+                ncp->nciop->get_size += buf_len * buf_type_size;
+            }
         }
     } else { /* WRITE_REQ */
         if (io_method == COLL_IO) {
@@ -1918,6 +1852,9 @@ ncmpii_req_aggregation(NC     *ncp,
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
+            else {
+                ncp->nciop->put_size += buf_len * buf_type_size;
+            }
         } else {
             TRACE_IO(MPI_File_write_at)(fh, offset, buf, buf_len, buf_type,
                                         &mpistatus);
@@ -1929,11 +1866,9 @@ ncmpii_req_aggregation(NC     *ncp,
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
-        }
-        if (mpireturn == MPI_SUCCESS) {
-            int put_size;
-            MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
-            ncp->nciop->put_size += put_size;
+            else {
+                ncp->nciop->put_size += buf_len * buf_type_size;
+            }
         }
     }
 
@@ -1955,46 +1890,29 @@ ncmpii_req_aggregation(NC     *ncp,
 
 /*----< ncmpii_wait_getput() >------------------------------------------------*/
 static int
-ncmpii_wait_getput(NC     *ncp,
-                   int     num_reqs,  /* # requests including subrequests */
-                   NC_req *req_head,  /* linked list not include subrequests */
-                   int     rw_flag,   /* WRITE_REQ or READ_REQ */
-                   int     io_method) /* COLL_IO or INDEP_IO */
+ncmpii_wait_getput(NC         *ncp,
+                   int         num_reqs,   /* # requests */
+                   NC_req     *reqs,       /* array of requests */
+                   int         rw_flag,    /* WRITE_REQ or READ_REQ */
+                   int         io_method,  /* COLL_IO or INDEP_IO */
+                   MPI_Offset  newnumrecs) /* new number of records */
 {
-    int i, j, err, status=NC_NOERR, access_interleaved=0;
-    NC_req *reqs, *cur_req;
-
-    /* pack the requests and sub-requests from the linked list into an array,
-     * so they can be sorted */
-    reqs = (NC_req*) NCI_Malloc((size_t)num_reqs * sizeof(NC_req));
-    i = 0;
-    cur_req = req_head;
-    while (cur_req != NULL) {
-        if (cur_req->num_subreqs == 0)
-            reqs[i++] = *cur_req;
-        else {
-            for (j=0; j<cur_req->num_subreqs; j++)
-                reqs[i++] = cur_req->subreqs[j];
-        }
-        cur_req = cur_req->next;
-    }
+    int i, err, status=NC_NOERR, access_interleaved=0;
 
-#ifndef _DISALLOW_POST_NONBLOCKING_API_IN_DEFINE_MODE
     /* move the offset calculation from posting API calls (pack_request) to
-     * wait call, such that posting a nonblocking request can be done in
-     * define mode  
+     * wait call, such that posting a nonblocking request can be made in
+     * define mode
      */  
     for (i=0; i<num_reqs; i++) {
         /* get the starting file offset for this request */
         ncmpii_get_offset(ncp, reqs[i].varp, reqs[i].start, NULL, NULL,
-                          reqs[i].rw_flag, &reqs[i].offset_start);
+                          rw_flag, &reqs[i].offset_start);
 
         /* get the ending file offset for this request */
         ncmpii_get_offset(ncp, reqs[i].varp, reqs[i].start, reqs[i].count,
-                          reqs[i].stride, reqs[i].rw_flag, &reqs[i].offset_end);
+                          reqs[i].stride, rw_flag, &reqs[i].offset_end);
         reqs[i].offset_end += reqs[i].varp->xsz - 1;
     }
-#endif
 
     /* check if reqs[].offset_start are in an increasing order */
     for (i=1; i<num_reqs; i++) {
@@ -2021,32 +1939,18 @@ ncmpii_wait_getput(NC     *ncp,
 
     /* Update the number of records if new records have been created.
      * For nonblocking APIs, there is no way for a process to know whether
-     * others write to a record variable or not. Hence, we must sync the
-     * number of records for write request
+     * others write to a record variable or not. Note newnumrecs has been
+     * sync-ed and always >= ncp->numrecs.
      */
     if (rw_flag == WRITE_REQ) {
-        /* Because netCDF allows only one unlimited dimension, find the
-         * maximum number of records from all nonblocking requests and
-         * update newnumrecs once
-         */
-        MPI_Offset newnumrecs = ncp->numrecs;
-        for (i=0; i<num_reqs; i++) {
-            if (!IS_RECVAR(reqs[i].varp)) continue; /* not a record var */
-            if (reqs[i].bnelems == 0) continue; /* 0-len or invalid request */
-
-            newnumrecs = MAX(newnumrecs, reqs[i].start[0] + reqs[i].count[0]);
-        }
-
         if (io_method == COLL_IO) {
-            /* sync numrecs in memory and file. Note that even this process
-             * does not write to record variable, others might. Note in
-             * ncmpii_sync_numrecs(), new_numrecs is checked against
-             * ncp->numrecs and if NC_SHARE is set, MPI_File_sync() will
-             * be called.
-             */
-            err = ncmpii_sync_numrecs(ncp, newnumrecs);
-            if (status == NC_NOERR) status = err;
-            /* retain the first error if there is any */
+            if (newnumrecs > ncp->numrecs) {
+                /* update new record number in file */
+                err = ncmpii_write_numrecs(ncp, newnumrecs);
+                if (status == NC_NOERR) status = err;
+                /* retain the first error if there is any */
+                ncp->numrecs = newnumrecs;
+            }
         }
         else { /* INDEP_IO */
             if (ncp->numrecs < newnumrecs) {
@@ -2076,8 +1980,6 @@ ncmpii_wait_getput(NC     *ncp,
         }
     }
 
-    if (reqs != NULL) NCI_Free(reqs);
-
     return status;
 }
 
@@ -2095,11 +1997,12 @@ ncmpii_mgetput(NC           *ncp,
                int           rw_flag,     /* WRITE_REQ or READ_REQ */
                int           io_method)   /* COLL_IO or INDEP_IO */
 {
-    int i, j, len=0, status=NC_NOERR, mpireturn, err;
+    int i, j, len=0, status=NC_NOERR, mpireturn, err, buf_type_size=0;
     void *buf=NULL;
     MPI_Status mpistatus;
     MPI_Datatype filetype, buf_type=MPI_BYTE;
     MPI_File fh;
+    MPI_Offset offset=0;
 
     if (io_method == COLL_IO)
         fh = ncp->nciop->collective_fh;
@@ -2118,7 +2021,7 @@ ncmpii_mgetput(NC           *ncp,
     }
 
     /* set the MPI-IO fileview */
-    MPI_Offset offset=0;
+    offset=0;
     err = ncmpii_file_set_view(ncp, fh, &offset, filetype);
     if (err != NC_NOERR) {
         num_reqs = 0; /* skip this request */
@@ -2224,6 +2127,8 @@ ncmpii_mgetput(NC           *ncp,
     }
     /* if (buf_type == MPI_BYTE) then the whole buf is contiguous */
 
+    MPI_Type_size(buf_type, &buf_type_size);
+
     if (rw_flag == READ_REQ) {
         if (io_method == COLL_IO) {
             TRACE_IO(MPI_File_read_at_all)(fh, offset, buf, len, buf_type,
@@ -2236,6 +2141,10 @@ ncmpii_mgetput(NC           *ncp,
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
+            else {
+                /* update the number of bytes read since file open */
+                ncp->nciop->get_size += len * buf_type_size;
+            }
         } else {
             TRACE_IO(MPI_File_read_at)(fh, offset, buf, len, buf_type,
                                        &mpistatus);
@@ -2247,12 +2156,11 @@ ncmpii_mgetput(NC           *ncp,
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
+            else {
+                /* update the number of bytes read since file open */
+                ncp->nciop->get_size += len * buf_type_size;
+            }
         }
-        /* update the number of bytes read since file open */
-        int get_size;
-        MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
-        ncp->nciop->get_size += get_size;
-
     } else { /* WRITE_REQ */
         if (io_method == COLL_IO) {
             TRACE_IO(MPI_File_write_at_all)(fh, offset, buf, len, buf_type,
@@ -2265,6 +2173,10 @@ ncmpii_mgetput(NC           *ncp,
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
+            else {
+                /* update the number of bytes written since file open */
+                ncp->nciop->put_size += len * buf_type_size;
+            }
         } else {
             TRACE_IO(MPI_File_write_at)(fh, offset, buf, len, buf_type,
                                         &mpistatus);
@@ -2276,11 +2188,11 @@ ncmpii_mgetput(NC           *ncp,
                     DEBUG_ASSIGN_ERROR(status, err)
                 }
             }
+            else {
+                /* update the number of bytes written since file open */
+                ncp->nciop->put_size += len * buf_type_size;
+            }
         }
-        /* update the number of bytes written since file open */
-        int put_size;
-        MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
-        ncp->nciop->put_size += put_size;
     }
 
     if (buf_type != MPI_BYTE) /* free user buffer type */
@@ -2294,88 +2206,3 @@ ncmpii_mgetput(NC           *ncp,
 
     return status;
 }
-
-/*----< ncmpii_set_iget_callback() >-----------------------------------------*/
-/* this subroutine is only used by iget_varn API family and when its buftype
- * argument indicated a noncontiguous data type. In this case, tmpBuf is never
- * == userBuf
- *
- * iget_varn() divides userBuf into pieces, each is used in an iget_varm() and
- * stored in a cur_req->buf. We cannot unpack each req->buf individually, as
- * req->buf may need to type converted. So at the end of wait(), we unpack the
- * entire tmpBuf into userBuf.
- */
-int ncmpii_set_iget_callback(NC           *ncp,
-                             int           reqid,
-                             void         *tmpBuf,
-                             void         *userBuf,
-                             int           userBufCount,
-                             MPI_Datatype  userBufType)
-{
-    NC_req *cur_req;
-
-    if (reqid == NC_REQ_NULL) return NC_NOERR;
-
-    if (ncp->head == NULL) DEBUG_RETURN_ERROR(NC_EINVAL_REQUEST)
-
-    cur_req = ncp->head;
-    while (cur_req != NULL) {
-        /* find the first linked-list node with reqid, there may be more than
-         * one node with the same request ID
-         */
-        if (cur_req->id == reqid) {
-            MPI_Datatype dup_buftype;
-            MPI_Type_dup(userBufType, &dup_buftype);
-
-            cur_req->tmpBuf = tmpBuf;
-                     /* When not NULL, tmpBuf is an internal buffer allocated
-                      * in iget_varn(). At the end of nonblocking wait call,
-                      * tmpBuf will be unpacked to userBuf and freed.
-                      */
-            cur_req->userBuf = userBuf;
-                     /* User's buffer. iget_varn() divides userBuf into pieces,
-                      * each is used in an iget_varm() and stored in a
-                      * cur_req->buf.
-                      */
-            cur_req->bufcount = userBufCount;
-            cur_req->buftype  = dup_buftype;
-            break;
-        }
-        cur_req = cur_req->next;
-    }
-    if (cur_req == NULL) DEBUG_RETURN_ERROR(NC_EINVAL_REQUEST)
-
-    return NC_NOERR;
-}
-
-/*----< ncmpii_set_iput_callback() >-----------------------------------------*/
-/* this subroutine is only used by iput_varn API family, to tell wait() to
- * free the temporary buffer at the end.
- */
-int ncmpii_set_iput_callback(NC   *ncp,
-                             int   reqid,
-                             void *tmpPutBuf)
-{
-    int found_req_id=NC_REQ_NULL;
-    NC_req *cur_req;
-
-    if (reqid == NC_REQ_NULL) return NC_NOERR;
-
-    if (ncp->head == NULL) DEBUG_RETURN_ERROR(NC_EINVAL_REQUEST)
-
-    cur_req = ncp->head;
-    while (cur_req != NULL) {
-        /* there may be more than one linked-list node with the same ID */
-        if (cur_req->id == reqid) {
-            /* set tmpBuf only on the first node, so it is freed just once */
-            if (found_req_id == NC_REQ_NULL) cur_req->tmpBuf = tmpPutBuf;
-            found_req_id = reqid;
-        }
-        if (found_req_id != NC_REQ_NULL && cur_req->id != found_req_id)
-            break; /* requests with same ID are in consecutive linked nodes */
-        cur_req = cur_req->next;
-    }
-    if (found_req_id == NC_REQ_NULL) DEBUG_RETURN_ERROR(NC_EINVAL_REQUEST)
-
-    return NC_NOERR;
-}
diff --git a/src/lib/pnetcdf.h.in b/src/lib/pnetcdf.h.in
index b967db2..8a2bd08 100644
--- a/src/lib/pnetcdf.h.in
+++ b/src/lib/pnetcdf.h.in
@@ -1,19 +1,29 @@
 /*
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
+ * 
+ * $Id: pnetcdf.h.in 2615 2016-11-13 23:58:41Z wkliao $
+ *
+ * @configure_input@
  */
-/* $Id: pnetcdf.h.in 2319 2016-02-04 08:04:01Z wkliao $ */
-

+
 #ifndef _PNETCDF_
 #define _PNETCDF_
 
 #include <mpi.h>
 
-#ifndef PNETCDF_VERSION_MAJOR
+#define PNETCDF_VERSION       "@PNETCDF_VERSION@"
 #define PNETCDF_VERSION_MAJOR @PNETCDF_VERSION_MAJOR@
 #define PNETCDF_VERSION_MINOR @PNETCDF_VERSION_MINOR@
-#define PNETCDF_VERSION_SUB @PNETCDF_VERSION_SUB@
-#endif
+#define PNETCDF_VERSION_SUB   @PNETCDF_VERSION_SUB@
+#define PNETCDF_RELEASE_DATE  "@PNETCDF_RELEASE_DATE@"
+
+/* list of PnetCDF options enabled/disabled at configure time */
+#define PNETCDF_ERANGE_FILL       @ENABLE_ERANGE_FILL@
+#define PNETCDF_SUBFILING         @ENABLE_SUBFILING@
+#define PNETCDF_RELAX_COORD_BOUND @RELAX_COORD_BOUND@
+#define PNETCDF_DEBUG_MODE        @PNETCDF_DEBUG@
+
 
 #if defined(__cplusplus)
 extern "C" {
@@ -539,18 +549,20 @@ by the desired type. */
 #define NC_EQUOTA			(-225) /**< Quota exceeded */
 #define NC_ENULLSTART			(-226) /**< argument start is a NULL pointer */
 #define NC_ENULLCOUNT			(-227) /**< argument count is a NULL pointer */
-#define NC_EINVAL_CMODE			(-228) /**< Invalid file create mode, cannot have both NC_64BIT_OFFSET & NC_64BIT_DATA */
+#define NC_EINVAL_CMODE			(-228) /**< Invalid file create mode */
 #define NC_ETYPESIZE			(-229) /**< MPI derived data type size error (bigger than the variable size) */
 #define NC_ETYPE_MISMATCH		(-230) /**< element type of the MPI derived data type mismatches the variable type */
 #define NC_ETYPESIZE_MISMATCH		(-231) /**< file type size mismatches buffer type size */
 #define NC_ESTRICTCDF2			(-232) /**< Attempting CDF-5 operation on CDF-2 file */
 #define NC_ENOTRECVAR			(-233) /**< Attempting operation only for record variables */
 #define NC_ENOTFILL			(-234) /**< Attempting to fill a variable when its fill mode is off */
+#define NC_EINVAL_OMODE			(-235) /**< Invalid file open mode */
+#define NC_EPENDING			(-236) /**< Pending nonblocking request is found at file close */
 /* add new error here */
 
 /* header inconsistency errors start from -250 */
 #define NC_EMULTIDEFINE			(-250) /**< NC definitions on multiprocesses conflict */
-#define NC_EMULTIDEFINE_OMODE		(-251) /**< create/open mode are inconsistent across processes */
+#define NC_EMULTIDEFINE_OMODE		(-251) /**< inconsistent file open modes among processes */
 #define NC_EMULTIDEFINE_DIM_NUM		(-252) /**< inconsistent number of dimensions */
 #define NC_EMULTIDEFINE_DIM_SIZE	(-253) /**< inconsistent size of dimension */
 #define NC_EMULTIDEFINE_DIM_NAME	(-254) /**< inconsistent dimension names */
@@ -572,6 +584,7 @@ by the desired type. */
 #define NC_EMULTIDEFINE_FILL_MODE	(-270) /**< inconsistent dataset fill mode */
 #define NC_EMULTIDEFINE_VAR_FILL_MODE	(-271) /**< inconsistent variable fill mode */
 #define NC_EMULTIDEFINE_VAR_FILL_VALUE	(-272) /**< inconsistent variable fill value */
+#define NC_EMULTIDEFINE_CMODE		(-273) /**< inconsistent file create modes among processes */
 
 #define NC_EMULTIDEFINE_FIRST		NC_EMULTIDEFINE
 #define NC_EMULTIDEFINE_LAST		NC_EMULTIDEFINE_FNC_ARGS
@@ -607,7 +620,9 @@ by the desired type. */
 
 const char* ncmpi_strerror(int err);
 
-/* Begin Dataset Functions */
+const char* ncmpi_strerrno(int err);
+
+/* Begin File Functions */
 
 int ncmpi_create(MPI_Comm comm, const char *path, int cmode, MPI_Info info, int *ncidp);
 
@@ -645,11 +660,9 @@ int ncmpi_set_fill(int ncid, int fillmode, int *old_modep);
 
 int ncmpi_def_var_fill(int ncid, int varid, int no_fill, void *fill_value);
 
-int ncmpi_inq_var_fill(int ncid, int varid, int *no_fill, void *fill_value);
-
 int ncmpi_fill_var_rec(int ncid, int varid, MPI_Offset recno);
 
-/* End Dataset Functions */
+/* End File Functions */
 
 /* Begin Define Mode Functions */
 
@@ -732,6 +745,8 @@ int ncmpi_inq_files_opened(int *num, int *ncids);
 
 int ncmpi_inq_recsize(int ncid, MPI_Offset *recsize);
 
+int ncmpi_inq_var_fill(int ncid, int varid, int *no_fill, void *fill_value);
+
 /* End Inquiry Functions */
 
 /* Begin _att */
diff --git a/src/lib/string.c b/src/lib/string.c
index 3665008..aba6589 100644
--- a/src/lib/string.c
+++ b/src/lib/string.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: string.c 2196 2015-11-27 22:31:05Z wkliao $ */
+/* $Id: string.c 2495 2016-09-26 06:42:18Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -24,6 +24,7 @@
 #include "macro.h"
 
 
+/*----< ncmpii_free_NC_string() >--------------------------------------------*/
 /*
  * Free string, and, if needed, its values.
  * Formerly
@@ -244,7 +245,7 @@ ncmpii_NC_check_name_CDF2(const char *name)
 		DEBUG_RETURN_ERROR(NC_EBADNAME)
 
 	/* check validity of any UTF-8 */
-	utf8_stat = utf8proc_check((const unsigned char *)name);
+	utf8_stat = ncmpii_utf8proc_check((const unsigned char *)name);
 	if (utf8_stat < 0)
 	    DEBUG_RETURN_ERROR(NC_EBADNAME)
 
@@ -291,7 +292,7 @@ NC_new_string(count, str)
  */
 NC_string *
 ncmpii_new_NC_string(size_t      slen,
-                     const char *str)
+                     const char *str)  /* must be already normalized */
 {
     /* str may not be NULL terminated */
     NC_string *ncstrp;
diff --git a/src/lib/subfile.c b/src/lib/subfile.c
index ca909e8..1e5a109 100644
--- a/src/lib/subfile.c
+++ b/src/lib/subfile.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: subfile.c 2196 2015-11-27 22:31:05Z wkliao $ */
+/* $Id: subfile.c 2475 2016-09-05 23:15:29Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 #include "subfile.h"
 #ifdef TAU_SSON
diff --git a/src/lib/utf8proc.c b/src/lib/utf8proc.c
index 756a10b..4632a91 100644
--- a/src/lib/utf8proc.c
+++ b/src/lib/utf8proc.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: utf8proc.c 2220 2015-12-11 23:07:44Z wkliao $ */
+/* $Id: utf8proc.c 2475 2016-09-05 23:15:29Z wkliao $ */
 
 /*
  *  Copyright (c) 2006-2007 Jan Behrens, FlexiGuided GmbH, Berlin
@@ -48,12 +48,13 @@
 
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include "utf8proc.h"
 #include "utf8proc_data.h"
 
+static
 const int8_t utf8proc_utf8class[256] = {
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -106,6 +107,8 @@ const int8_t utf8proc_utf8class[256] = {
 #define UTF8PROC_BOUNDCLASS_LVT     10
 
 
+#ifdef UNUSED_APIS
+static
 const char *utf8proc_errmsg(ssize_t errcode) {
   switch (errcode) {
     case UTF8PROC_ERROR_NOMEM:
@@ -122,7 +125,9 @@ const char *utf8proc_errmsg(ssize_t errcode) {
     return "An unknown error occurred while processing UTF-8 data.";
   }
 }
+#endif
 
+static
 ssize_t utf8proc_iterate(
   const uint8_t *str, ssize_t slen, int32_t *dst
 ) {
@@ -163,13 +168,17 @@ ssize_t utf8proc_iterate(
   return length;
 }
 
+#ifdef UNUSED_APIS
+static
 bool utf8proc_codepoint_valid(int32_t uc) {
   if (uc < 0 || uc >= 0x110000 ||
     ((uc & 0xFFFF) >= 0xFFFE) || (uc >= 0xD800 && uc < 0xE000) ||
     (uc >= 0xFDD0 && uc < 0xFDF0)) return false;
   else return true;
 }
+#endif
 
+static
 ssize_t utf8proc_encode_char(int32_t uc, uint8_t *dst) {
   if (uc < 0x00) {
     return 0;
@@ -200,6 +209,9 @@ ssize_t utf8proc_encode_char(int32_t uc, uint8_t *dst) {
   } else return 0;
 }
 
+#define UTF8PROC_GET_PROPERTY(uc) (&utf8proc_properties[utf8proc_stage2table[utf8proc_stage1table[uc >> 8] + (uc & 0xFF)]])
+#if 0
+static
 const utf8proc_property_t *utf8proc_get_property(int32_t uc) {
   /*  // ASSERT: uc >= 0 && uc < 0x110000*/
   return utf8proc_properties + (
@@ -208,18 +220,20 @@ const utf8proc_property_t *utf8proc_get_property(int32_t uc) {
     ]
   );
 }
+#endif
 
 #define utf8proc_decompose_lump(replacement_uc) \
   return utf8proc_decompose_char((replacement_uc), dst, bufsize, \
   options & ~UTF8PROC_LUMP, last_boundclass)
 
+static
 ssize_t utf8proc_decompose_char(int32_t uc, int32_t *dst, ssize_t bufsize,
     int options, int *last_boundclass) {
   /*// ASSERT: uc >= 0 && uc < 0x110000*/
   const utf8proc_property_t *property;
   utf8proc_propval_t category;
   int32_t hangul_sindex;
-  property = utf8proc_get_property(uc);
+  property = UTF8PROC_GET_PROPERTY(uc);
   category = property->category;
   hangul_sindex = uc - UTF8PROC_HANGUL_SBASE;
   if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
@@ -358,6 +372,7 @@ ssize_t utf8proc_decompose_char(int32_t uc, int32_t *dst, ssize_t bufsize,
   return 1;
 }
 
+static
 ssize_t utf8proc_decompose(
   const uint8_t *str, ssize_t slen,
   int32_t *buffer, ssize_t bufsize, int options
@@ -405,8 +420,8 @@ ssize_t utf8proc_decompose(
       const utf8proc_property_t *property1, *property2;
       uc1 = buffer[pos];
       uc2 = buffer[pos+1];
-      property1 = utf8proc_get_property(uc1);
-      property2 = utf8proc_get_property(uc2);
+      property1 = UTF8PROC_GET_PROPERTY(uc1);
+      property2 = UTF8PROC_GET_PROPERTY(uc2);
       if (property1->combining_class > property2->combining_class &&
           property2->combining_class > 0) {
         buffer[pos] = uc2;
@@ -420,6 +435,7 @@ ssize_t utf8proc_decompose(
   return wpos;
 }
 
+static
 ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) {
   /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored
      ASSERT: 'buffer' has one spare byte of free space at the end! */
@@ -464,7 +480,7 @@ ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) {
     int32_t composition;
     for (rpos = 0; rpos < length; rpos++) {
       current_char = buffer[rpos];
-      current_property = utf8proc_get_property(current_char);
+      current_property = UTF8PROC_GET_PROPERTY(current_char);
       if (starter && current_property->combining_class > max_combining_class) {
 	/*        // combination perhaps possible*/
         int32_t hangul_lindex;
@@ -493,7 +509,7 @@ ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) {
           }
         }
         if (!starter_property) {
-          starter_property = utf8proc_get_property(*starter);
+          starter_property = UTF8PROC_GET_PROPERTY(*starter);
         }
         if (starter_property->comb1st_index >= 0 &&
             current_property->comb2nd_index >= 0) {
@@ -502,7 +518,7 @@ ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) {
             current_property->comb2nd_index
           ];
           if (composition >= 0 && (!(options & UTF8PROC_STABLE) ||
-              !(utf8proc_get_property(composition)->comp_exclusion))) {
+              !(UTF8PROC_GET_PROPERTY(composition)->comp_exclusion))) {
             *starter = composition;
             starter_property = NULL;
             continue;
@@ -535,6 +551,7 @@ ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) {
   }
 }
 
+static
 ssize_t utf8proc_map(
   const uint8_t *str, ssize_t slen, uint8_t **dstptr, int options
 ) {
@@ -564,20 +581,25 @@ ssize_t utf8proc_map(
   return result;
 }
 
+#ifdef UNUSED_APIS
+static
 uint8_t *utf8proc_NFD(const uint8_t *str) {
   uint8_t *retval;
   utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
     UTF8PROC_DECOMPOSE);
   return retval;
 }
+#endif
 
-uint8_t *utf8proc_NFC(const uint8_t *str) {
+uint8_t* ncmpii_utf8proc_NFC(const uint8_t *str) {
   uint8_t *retval;
   utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
     UTF8PROC_COMPOSE);
   return retval;
 }
 
+#ifdef UNUSED_APIS
+static
 uint8_t *utf8proc_NFKD(const uint8_t *str) {
   uint8_t *retval;
   utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
@@ -585,14 +607,16 @@ uint8_t *utf8proc_NFKD(const uint8_t *str) {
   return retval;
 }
 
+static
 uint8_t *utf8proc_NFKC(const uint8_t *str) {
   uint8_t *retval;
   utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
     UTF8PROC_COMPOSE | UTF8PROC_COMPAT);
   return retval;
 }
+#endif
 
-ssize_t utf8proc_check(const uint8_t *str) {
+ssize_t  ncmpii_utf8proc_check(const uint8_t *str) {
   ssize_t result;
   result = utf8proc_decompose(str, 0, NULL, 0,
 			      UTF8PROC_NULLTERM | UTF8PROC_STABLE);
diff --git a/src/lib/utf8proc.h b/src/lib/utf8proc.h
index 41ae4ec..ded2aec 100644
--- a/src/lib/utf8proc.h
+++ b/src/lib/utf8proc.h
@@ -2,7 +2,7 @@
  *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: utf8proc.h 2220 2015-12-11 23:07:44Z wkliao $ */
+/* $Id: utf8proc.h 2475 2016-09-05 23:15:29Z wkliao $ */
 
 /*
  *  Copyright (c) 2006-2007 Jan Behrens, FlexiGuided GmbH, Berlin
@@ -48,7 +48,7 @@
  *  - stripping of control characters
  *  - stripping of character marks (accents, etc.)
  *  - transformation of LF, CRLF, CR and NEL to line-feed (LF)
- *    or to the unicode chararacters for paragraph separation (PS)
+ *    or to the unicode characters for paragraph separation (PS)
  *    or line separation (LS).
  *  - unicode case folding (for case insensitive string comparisons)
  *  - rejection of illegal UTF-8 data
@@ -61,9 +61,14 @@
 #ifndef UTF8PROC_H
 #define UTF8PROC_H
 
+/* Note this header file requires some constants defined in ncconfig.h. Please
+ * make sure ncconfig.h is included in any C file before including this file.
+ * We cannot include ncconfig.h here due to the compiler warning complaining
+ * about constants being redefined (caused by including ncconfig.h twice.)
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
+ */
 
 #include <stdlib.h>
 #ifdef HAVE_STDBOOL_H
@@ -255,6 +260,7 @@ typedef struct utf8proc_property_struct {
 #define UTF8PROC_DECOMP_TYPE_FRACTION 15
 #define UTF8PROC_DECOMP_TYPE_COMPAT   16
 
+#if 0
 extern const int8_t utf8proc_utf8class[256];
 
 const char *utf8proc_errmsg(ssize_t errcode);
@@ -320,7 +326,7 @@ ssize_t utf8proc_decompose_char(
  *  In case of success the number of chars written is returned,
  *  in case of an error, a negative error code is returned.
  *  If the number of written chars would be bigger than 'bufsize',
- *  the buffer (up to 'bufsize') has inpredictable data, and the needed
+ *  the buffer (up to 'bufsize') has unpredictable data, and the needed
  *  buffer size is returned.
  *  WARNING: The parameter 'uc' has to be in the range of 0x0000 to
  *           0x10FFFF, otherwise the program might crash!
@@ -340,7 +346,7 @@ ssize_t utf8proc_decompose(
  *  In case of success the number of chars written is returned,
  *  in case of an error, a negative error code is returned.
  *  If the number of written chars would be bigger than 'bufsize',
- *  the buffer (up to 'bufsize') has inpredictable data, and the needed
+ *  the buffer (up to 'bufsize') has unpredictable data, and the needed
  *  buffer size is returned.
  */
 
@@ -383,7 +389,7 @@ ssize_t utf8proc_map(
  *  In case of success the length of the new string is returned,
  *  otherwise a negative error code is returned.
  *  NOTICE: The memory of the new UTF-8 string will have been allocated with
- *          'malloc', and has theirfore to be freed with 'free'.
+ *          'malloc', and has therefore to be freed with 'free'.
  */
 
 uint8_t *utf8proc_NFD(const uint8_t *str);
@@ -394,8 +400,10 @@ uint8_t *utf8proc_NFKC(const uint8_t *str);
  *  Returns a pointer to newly allocated memory of a NFD, NFC, NFKD or NFKC
  *  normalized version of the null-terminated string 'str'.
  */
+#endif
+uint8_t* ncmpii_utf8proc_NFC(const uint8_t *str);
 
-ssize_t utf8proc_check(const uint8_t *str);
+ssize_t  ncmpii_utf8proc_check(const uint8_t *str);
 /*
  * Just checks UTF-8 string for validity, returns 0 if valid or one of
  * the negative UTF8PROC_ERROR_* codes if invalid or memory exhausted
diff --git a/src/lib/utf8proc_data.h b/src/lib/utf8proc_data.h
index 475be23..8263dcb 100644
--- a/src/lib/utf8proc_data.h
+++ b/src/lib/utf8proc_data.h
@@ -2,7 +2,7 @@
  *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: utf8proc_data.h 1468 2013-10-26 16:53:18Z wkliao $ */
+/* $Id: utf8proc_data.h 2359 2016-03-19 21:13:48Z wkliao $ */
 
 /*
  *  This file contains derived data from a modified version of the
@@ -47,7 +47,7 @@
  *  authorization of the copyright holder.
  */
 
-
+static
 const int32_t utf8proc_sequences[] = {
   97, -1, 98, -1, 99, -1, 100, 
   -1, 101, -1, 102, -1, 103, -1, 104, 
@@ -1489,6 +1489,7 @@ const int32_t utf8proc_sequences[] = {
   -1, 40709, -1, 40719, -1, 40726, -1, 173568, 
   -1, };
 
+static
 const uint16_t utf8proc_stage1table[] = {
   0, 256, 512, 768, 1024, 1280, 1536, 
   1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 
@@ -2036,6 +2037,7 @@ const uint16_t utf8proc_stage1table[] = {
   15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
   23040, };
 
+static
 const uint16_t utf8proc_stage2table[] = {
   1, 1, 1, 1, 1, 1, 1, 
   1, 1, 2, 3, 2, 4, 3, 1, 
@@ -4951,6 +4953,7 @@ const uint16_t utf8proc_stage2table[] = {
   3440, 3440, 3440, 3440, 3440, 3440, 3440, 0, 
   0, };
 
+static
 const utf8proc_property_t utf8proc_properties[] = {
   {0, 0, 0, 0, NULL, false, -1, -1, -1, -1, -1, false},
   {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
@@ -10572,6 +10575,7 @@ const utf8proc_property_t utf8proc_properties[] = {
   {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
 };
 
+static
 const int32_t utf8proc_combinations[] = {
   192, 193, 194, 195, 196, 197, -1, 
   256, 258, 260, 550, 461, -1, -1, 512, 
diff --git a/src/lib/util.c b/src/lib/util.c
index 50c14fa..927fb9a 100644
--- a/src/lib/util.c
+++ b/src/lib/util.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: util.c 2214 2015-12-08 00:33:40Z wkliao $ */
+/* $Id: util.c 2597 2016-11-04 22:12:08Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -13,27 +13,29 @@
 #include <mpi.h>
 #include "nc.h"
 #include "macro.h"
+#include "ncmpidtype.h"
 
 /*----< ncmpii_sanity_check() >----------------------------------------------*/
 int ncmpii_sanity_check(int               ncid,
                         int               varid,
                         const MPI_Offset *start,
                         const MPI_Offset *count,
-                        MPI_Offset        bufcount,
+                        const MPI_Offset  bufcount,
+                        MPI_Datatype      buftype,  /* internal datatype */
                         enum API_KIND     api,
+                        int               isFlexibleAPI,
                         int               mustInDataMode,
-                        int               isFlexAPI,
                         int               rw_flag,
                         int               io_method,
-                        NC              **ncp,
-                        NC_var          **varp)
+                        NC              **ncp,   /* OUT */
+                        NC_var          **varp)  /* OUT */
 {
     /* all errors detected here are fatal, must return immediately */
-    int status;
+    int err;
 
     /* check if ncid is valid */
-    status = ncmpii_NC_check_id(ncid, ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, ncp);
+    if (err != NC_NOERR) return err;
     /* For invalid ncid, we must return error now, as there is no way to
      * continue with invalid ncp. However, collective APIs might hang if this
      * error occurs only on a subset of processes
@@ -42,51 +44,78 @@ int ncmpii_sanity_check(int               ncid,
     /* if this call must be made in data mode, check if currently is in define
      * mode */
     if (mustInDataMode && NC_indef(*ncp)) {
-        DEBUG_ASSIGN_ERROR(status, NC_EINDEFINE)
+        DEBUG_ASSIGN_ERROR(err, NC_EINDEFINE)
         goto fn_exit;
     }
 
     /* check file write permission if this is write request */
     if (rw_flag == WRITE_REQ && NC_readonly(*ncp)) {
-        DEBUG_ASSIGN_ERROR(status, NC_EPERM)
+        DEBUG_ASSIGN_ERROR(err, NC_EPERM)
         goto fn_exit;
     }
 
     if (io_method != NONBLOCKING_IO) { /* for blocking APIs */
         /* check if in the right collective or independent mode and initialize
          * MPI file handlers */
-        status = ncmpii_check_mpifh(*ncp, io_method);
-        if (status != NC_NOERR) goto fn_exit;
+        err = ncmpii_check_mpifh(*ncp, io_method);
+        if (err != NC_NOERR) goto fn_exit;
     }
 
     /* check if varid is valid */
-    status = ncmpii_NC_lookupvar(*ncp, varid, varp);
-    if (status != NC_NOERR) goto fn_exit;
+    err = ncmpii_NC_lookupvar(*ncp, varid, varp);
+    if (err != NC_NOERR) goto fn_exit;
+
+    /* check NC_ECHAR */
+    if (isFlexibleAPI) {
+        /* when buftype == MPI_DATATYPE_NULL, bufcount is ignored and this API
+         * assumes argument buf's data type matches the data type of variable
+         * defined in the file - no data conversion will be done.
+         */
+        if (buftype != MPI_DATATYPE_NULL) {
+            int isderived, el_size, buftype_is_contig;
+            MPI_Datatype ptype;
+            MPI_Offset   bnelems=0;
+
+            err = ncmpii_dtype_decode(buftype, &ptype, &el_size, &bnelems,
+                                      &isderived, &buftype_is_contig);
+            if (err != NC_NOERR) goto fn_exit;
+
+            err = NCMPII_ECHAR((*varp)->type, ptype);
+            if (err != NC_NOERR) goto fn_exit;
+        }
+        /* else case types are matched */
+    }
+    else {
+        err = NCMPII_ECHAR((*varp)->type, buftype);
+        if (err != NC_NOERR) goto fn_exit;
+    }
 
     /* for API var1, vara, vars, varm, and varn, start cannot be NULL */
     if (start == NULL && api >= API_VAR1 && (*varp)->ndims > 0) {
-        DEBUG_ASSIGN_ERROR(status, NC_ENULLSTART)
+        DEBUG_ASSIGN_ERROR(err, NC_EINVALCOORDS)
         goto fn_exit;
     }
 
     /* for API vara, vars, and varm, count cannot be NULL */
     if (count == NULL && api >= API_VARA && (*varp)->ndims > 0) {
-        DEBUG_ASSIGN_ERROR(status, NC_ENULLCOUNT)
+        DEBUG_ASSIGN_ERROR(err, NC_EEDGE)
         goto fn_exit;
     }
 
     /* for flexible APIs, bufcount cannot be negative */
-    if (isFlexAPI && bufcount < 0) {
-        DEBUG_ASSIGN_ERROR(status, NC_EINVAL)
+    if (bufcount < 0) {
+        DEBUG_ASSIGN_ERROR(err, NC_EINVAL)
         goto fn_exit;
     }
 
 fn_exit:
     if ((*ncp)->safe_mode == 1 && io_method == COLL_IO) {
-        int min_st;
-        MPI_Allreduce(&status, &min_st, 1, MPI_INT, MPI_MIN, (*ncp)->nciop->comm);
-        if (status == NC_NOERR) status = min_st;
+        int min_st, mpireturn;
+        TRACE_COMM(MPI_Allreduce)(&err, &min_st, 1, MPI_INT, MPI_MIN, (*ncp)->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR) err = min_st;
     }
-    return status;
+    return err;
 }
 
diff --git a/src/lib/var.c b/src/lib/var.c
index dfa77fd..7b6ecd0 100644
--- a/src/lib/var.c
+++ b/src/lib/var.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: var.c 2322 2016-02-26 22:47:06Z wkliao $ */
+/* $Id: var.c 2588 2016-10-30 04:14:15Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #ifdef HAVE_STDLIB_H
@@ -45,8 +45,7 @@ ncmpii_free_NC_var(NC_var *varp)
 
 /*----< ncmpii_new_x_NC_var() >-----------------------------------------------*/
 /*
- * Common code for ncmpii_new_NC_var()
- * and ncx_get_NC_var()
+ * Used by ncmpii_new_NC_var() and ncx_get_NC_var()
  */
 NC_var *
 ncmpii_new_x_NC_var(NC_string *strp,
@@ -94,50 +93,124 @@ ncmpii_new_x_NC_var(NC_string *strp,
     return varp;
 }
 
-
 /*----< ncmpii_new_NC_var() >------------------------------------------------*/
 /*
  * Formerly, NC_new_var()
  */
-static NC_var *
-ncmpii_new_NC_var(const char *uname,  /* variable name (NULL terminated) */
-                  nc_type     type,
-                  int         ndims,
-                  const int  *dimids)
+static int
+ncmpii_new_NC_var(NC_vararray  *vcap,
+                  const char   *name,  /* normalized variable name (NULL terminated) */
+                  nc_type       type,
+                  int           ndims,
+                  const int    *dimids,
+                  NC_var      **varp)
 {
     NC_string *strp;
-    NC_var *varp;
-
-    char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
-    if (name == NULL) return NULL;
 
     strp = ncmpii_new_NC_string(strlen(name), name);
-    free(name);
-    if (strp == NULL) return NULL;
+    if (strp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
 
-    varp = ncmpii_new_x_NC_var(strp, ndims);
-    if (varp == NULL ) {
+    *varp = ncmpii_new_x_NC_var(strp, ndims);
+    if (*varp == NULL ) {
         ncmpii_free_NC_string(strp);
-        return NULL;
+        DEBUG_RETURN_ERROR(NC_ENOMEM)
     }
 
-    varp->type = type;
+    (*varp)->type = type;
 
     if (ndims != 0 && dimids != NULL)
-        memcpy(varp->dimids, dimids, (size_t)ndims * SIZEOF_INT);
+        memcpy((*varp)->dimids, dimids, (size_t)ndims * SIZEOF_INT);
+
+#ifndef SEARCH_NAME_LINEARLY
+    if (vcap != NULL) { /* insert new var to hash table */
+        int key;
+        NC_nametable *nameT = vcap->nameT; /* var name lookup table */
+
+        /* hash the var name into a key for name lookup */
+        key = HASH_FUNC(name);
+
+        /* allocate or expand the space for nameT[key].list */
+        if (nameT[key].num % NC_NAME_TABLE_CHUNK == 0)
+            nameT[key].list = (int*) NCI_Realloc(nameT[key].list,
+                              (size_t)(nameT[key].num+NC_NAME_TABLE_CHUNK) * sizeof(int));
+
+        /* add the new variable ID to the name lookup table
+         * the new varid will be vcap->ndefined
+         */
+        nameT[key].list[nameT[key].num] = vcap->ndefined;
+        nameT[key].num++;
+    }
+    /* else case is for variable duplication called from dup_NC_var() */
+#endif
+
+    return NC_NOERR;
+}
+
+/*----< ncmpii_update_name_lookup_table() >----------------------------------*/
+/* remove the entry in lookup table for oldname and add a new entry for
+ * newname
+ */
+int
+ncmpii_update_name_lookup_table(NC_nametable *nameT,
+                                const int     id,
+                                const char   *oldname,  /*    normalized */
+                                const char   *unewname) /* un-normalized */
+{
+    int i, key;
+    char *name; /* normalized name string */
+
+    /* remove the old name from the lookup table
+     * hash the var name into a key for name lookup
+     */
+    key = HASH_FUNC(oldname);
+    for (i=0; i<nameT[key].num; i++) {
+        if (nameT[key].list[i] == id) break;
+    }
+    assert(i!=nameT[key].num);
+
+    /* coalesce the id array */
+    for (; i<nameT[key].num-1; i++)
+        nameT[key].list[i] = nameT[key].list[i+1]; 
+
+    /* decrease the number of IDs and free space if necessary */
+    nameT[key].num--;
+    if (nameT[key].num == 0) {
+        NCI_Free(nameT[key].list);
+        nameT[key].list = NULL;
+    }
+
+    /* normalized version of uname */
+    name = (char *)ncmpii_utf8proc_NFC((const unsigned char *)unewname);
+    if (name == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    /* hash the var name into a key for name lookup */
+    key = HASH_FUNC(name);
+    free(name);
+
+    /* add the new name to the lookup table
+     * Note unewname must have already been checked for existence
+     */
+    if (nameT[key].num % NC_NAME_TABLE_CHUNK == 0)
+        nameT[key].list = (int*) NCI_Realloc(nameT[key].list,
+                          (size_t)(nameT[key].num+NC_NAME_TABLE_CHUNK) * sizeof(int));
+    nameT[key].list[nameT[key].num] = id;
+    nameT[key].num++;
 
-    return(varp);
+    return NC_NOERR;
 }
 
+
 /*----< dup_NC_var() >--------------------------------------------------------*/
 NC_var *
 dup_NC_var(const NC_var *rvarp)
 {
+    int err;
     NC_var *varp;
 
-    varp = ncmpii_new_NC_var(rvarp->name->cp, rvarp->type, rvarp->ndims,
-                             rvarp->dimids);
-    if (varp == NULL) return NULL;
+    /* note that name in rvarp->name->cp is already normalized */
+    err = ncmpii_new_NC_var(NULL, rvarp->name->cp, rvarp->type, rvarp->ndims,
+                            rvarp->dimids, &varp);
+    if (err != NC_NOERR) return NULL;
 
     if (ncmpii_dup_NC_attrarray(&varp->attrs, &rvarp->attrs) != NC_NOERR) {
         ncmpii_free_NC_var(varp);
@@ -182,6 +255,13 @@ ncmpii_free_NC_vararray(NC_vararray *ncap)
     ncap->value    = NULL;
     ncap->nalloc   = 0;
     ncap->ndefined = 0;
+
+    /* free space allocated for var name lookup table */
+    for (i=0; i<HASH_TABLE_SIZE; i++) {
+        if (ncap->nameT[i].num > 0)
+            NCI_Free(ncap->nameT[i].list);
+        ncap->nameT[i].num = 0;
+    }
 }
 
 
@@ -224,6 +304,17 @@ ncmpii_dup_NC_vararray(NC_vararray       *ncap,
 
     ncap->ndefined = ref->ndefined;
 
+    /* duplicate var name lookup table */
+    for (i=0; i<HASH_TABLE_SIZE; i++) {
+        ncap->nameT[i].num = ref->nameT[i].num;
+        ncap->nameT[i].list = NULL;
+        if (ncap->nameT[i].num > 0) {
+            ncap->nameT[i].list = NCI_Malloc((size_t)ncap->nameT[i].num * sizeof(int));
+            memcpy(ncap->nameT[i].list, ref->nameT[i].list,
+                   (size_t)ncap->nameT[i].num * sizeof(int));
+        }
+    }
+
     return NC_NOERR;
 }
 
@@ -286,46 +377,71 @@ elem_NC_vararray(const NC_vararray *ncap,
 /* End vararray per se */
 
 
+#ifdef SEARCH_NAME_LINEARLY
 /*
  * Step thru NC_VARIABLE array, seeking match on name.
- * Return varid or -1 on not found.
- * *varpp is set to the appropriate NC_var.
+ * If found, set the variable ID pointed by vardip, otherwise return NC_ENOTVAR
  * Formerly (sort of)
 NC_hvarid
  */
 static int
-ncmpii_NC_findvar(const NC_vararray  *ncap,
-                  const char         *uname,
-                  NC_var            **varpp)
+ncmpii_NC_findvar(const NC_vararray *ncap,
+                  const char        *name,  /* normalized name */
+                  int               *varidp)
 {
     int varid;
     size_t nchars;
-    char *name;
     NC_var **loc;
 
     assert (ncap != NULL);
 
-    if (ncap->ndefined == 0) return -1;
+    if (ncap->ndefined == 0) return NC_ENOTVAR;
 
     loc = (NC_var **) ncap->value;
 
-    /* normalized version of uname */
-    name = (char *)utf8proc_NFC((const unsigned char *)uname);
-    if (name == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
     nchars = strlen(name);
 
     for (varid=0; varid<ncap->ndefined; varid++, loc++) {
         if ((*loc)->name->nchars == nchars &&
             strncmp((*loc)->name->cp, name, nchars) == 0) {
-            if (varpp != NULL)
-                *varpp = *loc;
-            free(name);
-            return (varid); /* Normal return */
+            if (varidp != NULL) *varidp = varid;
+            return NC_NOERR; /* found it */
         }
     }
-    free(name);
-    return (-1); /* not found */
+
+    return NC_ENOTVAR; /* not found */
 }
+#else
+/*----< ncmpii_NC_findvar() >------------------------------------------------*/
+/* Check if the name has been used.
+ * If yes, set the variable ID pointed by vardip, otherwise return NC_ENOTVAR
+ */
+static int
+ncmpii_NC_findvar(const NC_vararray  *ncap,
+                  const char         *name,  /* normalized name */
+                  int                *varidp)
+{
+    int i, key, varid;
+
+    assert (ncap != NULL);
+
+    if (ncap->ndefined == 0) return NC_ENOTVAR;
+
+    /* hash the var name into a key for name lookup */
+    key = HASH_FUNC(name);
+
+    /* check the list using linear search */
+    for (i=0; i<ncap->nameT[key].num; i++) {
+        varid = ncap->nameT[key].list[i];
+        if (strcmp(name, ncap->value[varid]->name->cp) == 0) {
+            if (varidp != NULL) *varidp = varid;
+            return NC_NOERR; /* the name already exists */
+        }
+    }
+
+    return NC_ENOTVAR; /* the name has never been used */
+}
+#endif
 
 /*
  * For a netcdf type
@@ -363,8 +479,7 @@ ncx_szof(nc_type type)
  * set varp->xsz, varp->shape and varp->len of a variable
  */
 int
-ncmpii_NC_var_shape64(NC                *ncp,
-                      NC_var            *varp,
+ncmpii_NC_var_shape64(NC_var            *varp,
                       const NC_dimarray *dims)
 {
     int i;
@@ -428,7 +543,7 @@ out :
      * We will check this in ncmpi_enddef() which calls ncmpii_NC_enddef()
      * which calls ncmpii_NC_check_vlens()
      *
-    if (! fIsSet(ncp->flags, NC_64BIT_DATA) && product >= X_UINT_MAX)
+    if (ncp->format < 5 && product >= X_UINT_MAX)
         DEBUG_RETURN_ERROR(NC_EVARSIZE)
      */
 
@@ -500,64 +615,173 @@ ncmpi_def_var(int         ncid,
               const int  *dimids,
               int        *varidp)
 {
-    int varid, file_ver, status;
-    NC *ncp;
-    NC_var *varp;
+    int err;
+    char *nname=NULL; /* normalized name */
+    NC *ncp=NULL;
+    NC_var *varp=NULL;
 
     /* check if ncid is valid */
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
+
+    /* check whether file's write permission */
+    if (NC_readonly(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EPERM)
+        goto err_check;
+    }
 
     /* check if called in define mode */
-    if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+    if (!NC_indef(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+        goto err_check;
+    }
+
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME) {
+        DEBUG_ASSIGN_ERROR(err, NC_EBADNAME)
+        goto err_check;
+    }
 
     /* check if the name string is legal for netcdf format */
-    file_ver = 1;
-    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
-        file_ver = 2;
-    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
-        file_ver = 5;
-    status = ncmpii_NC_check_name(name, file_ver);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_name(name, ncp->format);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
 
     /* check if type is a valid netcdf type */
-    status = ncmpii_cktype(file_ver, type);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_cktype(ncp->format, type);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
 
     /* TODO: make ndims of type MPI_Offset so ndims can be > 2^31-1 in CDF-5
     if ((ndims < 0) || ndims > X_INT_MAX) DEBUG_RETURN_ERROR(NC_EINVAL)
     */
-    if (ndims < 0) DEBUG_RETURN_ERROR(NC_EINVAL)
+    if (ndims < 0) {
+        DEBUG_ASSIGN_ERROR(err, NC_EINVAL)
+        goto err_check;
+    }
 
     /* there is an upperbound for the number of variables defined in a file */
-    if (ncp->vars.ndefined >= NC_MAX_VARS) DEBUG_RETURN_ERROR(NC_EMAXVARS)
+    if (ncp->vars.ndefined >= NC_MAX_VARS) {
+        DEBUG_ASSIGN_ERROR(err, NC_EMAXVARS)
+        goto err_check;
+    }
+
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
+    }
 
-    /* check whether the variable name has been used */
-    varid = ncmpii_NC_findvar(&ncp->vars, name, &varp);
-    if (varid != -1) DEBUG_RETURN_ERROR(NC_ENAMEINUSE)
+    /* check whether new name is already in use, for this API (def_var) the
+     * name should NOT already exist */
+    err = ncmpii_NC_findvar(&ncp->vars, nname, NULL);
+    if (err != NC_ENOTVAR) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENAMEINUSE)
+        goto err_check;
+    }
+    else
+        err = NC_NOERR;
+
+err_check:
+    if (ncp->safe_mode) {
+        int root_ndims, status, mpireturn;
+        char root_name[NC_MAX_NAME];
+
+        /* check if name is consistent among all processes */
+        if (name == NULL || *name == 0)
+            root_name[0] = 0;
+        else
+            strncpy(root_name, name, NC_MAX_NAME);
+        TRACE_COMM(MPI_Bcast)(root_name, NC_MAX_NAME, MPI_CHAR, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && strcmp(root_name, name))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_NAME)
+
+        /* check if type is consistent among all processes */
+        nc_type root_type=type;
+        TRACE_COMM(MPI_Bcast)(&root_type, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && root_type != type)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_TYPE)
+
+        /* check if ndims is consistent among all processes */
+        root_ndims=ndims;
+        TRACE_COMM(MPI_Bcast)(&root_ndims, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        }
+        if (err == NC_NOERR && root_ndims != ndims)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_NDIMS)
+
+        /* check if dimids is consistent among all processes */
+        if (root_ndims > 0) {
+            int root_dimids[NC_MAX_DIMS];
+            if (dimids != NULL)
+                memcpy(root_dimids, dimids, (size_t)root_ndims*sizeof(int));
+            else
+                memset(root_dimids, 0, (size_t)root_ndims*sizeof(int));
+            TRACE_COMM(MPI_Bcast)(root_dimids, root_ndims, MPI_INT, 0, ncp->nciop->comm);
+            if (mpireturn != MPI_SUCCESS) {
+                if (nname != NULL) free(nname);
+                return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+            }
+            if (err == NC_NOERR && dimids != NULL &&
+                memcmp(root_dimids, dimids, (size_t)root_ndims*sizeof(int)))
+                DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_DIMIDS)
+        }
+
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS) {
+            if (nname != NULL) free(nname);
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        }
+        if (err == NC_NOERR) err = status;
+    }
+
+    if (err != NC_NOERR) {
+        if (nname != NULL) free(nname);
+        return err;
+    }
+
+    assert(nname != NULL);
 
     /* create a new variable */
-    varp = ncmpii_new_NC_var(name, type, ndims, dimids);
-    if (varp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+    err = ncmpii_new_NC_var(&ncp->vars, nname, type, ndims, dimids, &varp);
+    free(nname);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
     /* set up array dimensional structures */
-    status = ncmpii_NC_var_shape64(ncp, varp, &ncp->dims);
-    if (status != NC_NOERR) {
+    err = ncmpii_NC_var_shape64(varp, &ncp->dims);
+    if (err != NC_NOERR) {
         ncmpii_free_NC_var(varp);
-        return status;
+        DEBUG_RETURN_ERROR(err)
     }
 
     /* Add a new handle to the end of an array of handles */
-    status = incr_NC_vararray(&ncp->vars, varp);
-    if (status != NC_NOERR) {
+    err = incr_NC_vararray(&ncp->vars, varp);
+    if (err != NC_NOERR) {
         ncmpii_free_NC_var(varp);
-        return status;
+        DEBUG_RETURN_ERROR(err)
     }
 
     if (varidp != NULL)
         *varidp = (int)ncp->vars.ndefined - 1; /* varid */
         /* ncp->vars.ndefined has been increased in incr_NC_vararray() */
 
+    assert(varp != NULL);
+
     /* default is NOFILL */
     varp->no_fill = 1;
 
@@ -569,27 +793,35 @@ ncmpi_def_var(int         ncid,
 
 
 /*----< ncmpi_inq_varid() >--------------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_varid(int         ncid,
                 const char *name,
-                int        *varid_ptr)
+                int        *varid)
 {
-    int status;
-    NC *ncp;
-    NC_var *varp;
-    int varid;
+    int err;
+    char *nname=NULL; /* normalized name */
+    NC *ncp=NULL;
+
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    if (name == NULL || *name == 0 || strlen(name) > NC_MAX_NAME)
+        DEBUG_RETURN_ERROR(NC_EBADNAME)
 
-    varid = ncmpii_NC_findvar(&ncp->vars, name, &varp);
-    if (varid == -1) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+    /* create a normalized character string */
+    nname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)name);
+    if (nname == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    err = ncmpii_NC_findvar(&ncp->vars, nname, varid);
+    free(nname);
+    if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
 
-    *varid_ptr = varid;
     return NC_NOERR;
 }
 
 /*----< ncmpi_inq_var() >----------------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_var(int      ncid,
               int      varid,
@@ -599,12 +831,12 @@ ncmpi_inq_var(int      ncid,
               int     *dimids,
               int     *nattsp)
 {
-    int status;
-    NC *ncp;
-    NC_var *varp;
+    int err;
+    NC *ncp=NULL;
+    NC_var *varp=NULL;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
     /* using NC_GLOBAL in varid is illegal for this API. See
      * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
@@ -647,17 +879,18 @@ ncmpi_inq_var(int      ncid,
 
 
 /*----< ncmpi_inq_varname() >------------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_varname(int   ncid,
                   int   varid,
                   char *name)
 {
-    int status;
-    NC *ncp;
-    NC_var *varp;
+    int err;
+    NC *ncp=NULL;
+    NC_var *varp=NULL;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
     /* using NC_GLOBAL in varid is illegal for this API. See
      * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
@@ -675,17 +908,18 @@ ncmpi_inq_varname(int   ncid,
 }
 
 /*----< ncmpi_inq_vartype() >------------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_vartype(int      ncid,
                   int      varid,
                   nc_type *typep)
 {
-    int status;
-    NC *ncp;
-    NC_var *varp;
+    int err;
+    NC *ncp=NULL;
+    NC_var *varp=NULL;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
     /* using NC_GLOBAL in varid is illegal for this API. See
      * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
@@ -701,15 +935,16 @@ ncmpi_inq_vartype(int      ncid,
 }
 
 /*----< ncmpi_inq_varndims() >-----------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_varndims(int ncid, int varid, int *ndimsp)
 {
-    int status;
-    NC *ncp;
-    NC_var *varp;
+    int err;
+    NC *ncp=NULL;
+    NC_var *varp=NULL;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
     /* using NC_GLOBAL in varid is illegal for this API. See
      * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
@@ -732,15 +967,16 @@ ncmpi_inq_varndims(int ncid, int varid, int *ndimsp)
 }
 
 /*----< ncmpi_inq_vardimid() >-----------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_vardimid(int ncid, int varid, int *dimids)
 {
-    int status;
-    NC *ncp;
-    NC_var *varp;
+    int err;
+    NC *ncp=NULL;
+    NC_var *varp=NULL;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
     /* using NC_GLOBAL in varid is illegal for this API. See
      * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
@@ -764,20 +1000,24 @@ ncmpi_inq_vardimid(int ncid, int varid, int *dimids)
 
 
 /*----< ncmpi_inq_varnatts() >------------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_varnatts(int  ncid,
                    int  varid,
                    int *nattsp)
 {
-    int status;
-    NC *ncp;
-    NC_var *varp;
+    int err;
+    NC *ncp=NULL;
+    NC_var *varp=NULL;
 
-    if (varid == NC_GLOBAL)
-        return ncmpi_inq_natts(ncid, nattsp);
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    if (varid == NC_GLOBAL) {
+        if (nattsp != NULL)
+            *nattsp = (int) ncp->attrs.ndefined;
+        return NC_NOERR;
+    }
 
     varp = elem_NC_vararray(&ncp->vars, varid);
     if (varp == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
@@ -789,104 +1029,159 @@ ncmpi_inq_varnatts(int  ncid,
 }
 
 /*----< ncmpi_rename_var() >--------------------------------------------------*/
-/* This API is collective if called in data mode */
+/* This API is collective.
+ * If the new name is longer than the old name, the netCDF file must be in
+ * define mode. Otherwise, it can be called in either define or data mode.
+ */
 int
 ncmpi_rename_var(int         ncid,
                  int         varid,
                  const char *newname)
 {
-    int file_ver, status=NC_NOERR, other, err, mpireturn;
-    NC *ncp;
-    NC_var *varp;
+    int err;
+    char *nnewname=NULL; /* normalized name */
+    NC *ncp=NULL;
+    NC_var *varp=NULL;
+    NC_string *newStr=NULL;
+
+    /* check whether ncid is valid */
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
+
+    /* check whether file's write permission */
+    if (NC_readonly(ncp)) {
+        DEBUG_ASSIGN_ERROR(err, NC_EPERM)
+        goto err_check;
+    }
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    /* check whether variable ID is valid */
+    err = ncmpii_NC_lookupvar(ncp, varid, &varp);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
 
-    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM)
+    if (newname == NULL || *newname == 0 || strlen(newname) > NC_MAX_NAME) {
+        DEBUG_ASSIGN_ERROR(err, NC_EBADNAME)
+        goto err_check;
+    }
 
-    /* check if variable ID is valid*/
-    status = ncmpii_NC_lookupvar(ncp, varid, &varp);
-    if (status != NC_NOERR) return status;
+    /* check whether new name is legal */
+    err = ncmpii_NC_check_name(newname, ncp->format);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
+    }
 
-    file_ver = 1;
-    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
-        file_ver = 2;
-    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
-        file_ver = 5;
+    /* create a normalized character string */ 
+    nnewname = (char *)ncmpii_utf8proc_NFC((const unsigned char *)newname);
+    if (nnewname == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
+    }
 
-    status = ncmpii_NC_check_name(newname, file_ver);
-    if (status != NC_NOERR) return status;
+    /* check whether new name is already in use, for this API (rename) the
+     * name should NOT already exist */
+    err = ncmpii_NC_findvar(&ncp->vars, nnewname, NULL);
+    if (err != NC_ENOTVAR) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENAMEINUSE)
+        goto err_check;
+    }
 
-    /* check for name in use */
-    other = ncmpii_NC_findvar(&ncp->vars, newname, &varp);
-    if (other != -1)
-        DEBUG_RETURN_ERROR(NC_ENAMEINUSE)
+    if (! NC_indef(ncp) && /* when file is in data mode */
+        varp->name->nchars < (MPI_Offset)strlen(nnewname)) {
+        /* must in define mode when newname is longer */
+        DEBUG_ASSIGN_ERROR(err, NC_ENOTINDEFINE)
+        goto err_check;
+    }
 
-    /* if called in define mode, just update to the NC object */
-    if (NC_indef(ncp)) {
-        NC_string *newStr = ncmpii_new_NC_string(strlen(newname), newname);
-        if (newStr == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+    newStr = ncmpii_new_NC_string(strlen(nnewname), nnewname);
+    if (newStr == NULL) {
+        DEBUG_ASSIGN_ERROR(err, NC_ENOMEM)
+        goto err_check;
+    }
 
-        ncmpii_free_NC_string(varp->name);
-        varp->name = newStr;
-        return NC_NOERR;
+#ifndef SEARCH_NAME_LINEARLY
+    /* update var name lookup table */
+    err = ncmpii_update_name_lookup_table(ncp->vars.nameT, varid,
+          ncp->vars.value[varid]->name->cp, nnewname);
+    if (err != NC_NOERR) {
+        DEBUG_TRACE_ERROR
+        goto err_check;
     }
-    /* else, not in define mode.
-     * if called in data mode (collective or independent), this function must
-     * be called collectively, i.e. all processes must participate.
-     */
+#endif
 
+err_check:
+    if (nnewname != NULL) free(nnewname);
     if (ncp->safe_mode) {
-        int nchars = (int)strlen(newname);
-        TRACE_COMM(MPI_Bcast)(&nchars, 1, MPI_INT, 0, ncp->nciop->comm);
+        int root_varid, status, mpireturn;
+        char root_name[NC_MAX_NAME];
+
+        /* check if newname is consistent among all processes */
+        if (newname == NULL || *newname == 0)
+            root_name[0] = 0;
+        else
+            strncpy(root_name, newname, NC_MAX_NAME);
+        TRACE_COMM(MPI_Bcast)(root_name, NC_MAX_NAME, MPI_CHAR, 0, ncp->nciop->comm);
         if (mpireturn != MPI_SUCCESS)
-            return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && strcmp(root_name, newname))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_NAME)
 
-        if (nchars != (int) strlen(newname)) {
-            /* newname's length is inconsistent with root's */
-            printf("Warning: variable name(%s) used in %s() is inconsistent\n",
-                   newname, __func__);
-            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_VAR_NAME)
-        }
+        /* check if varid is consistent across all processes */
+        root_varid = varid;
+        TRACE_COMM(MPI_Bcast)(&root_varid, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+        if (err == NC_NOERR && root_varid != varid)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_FNC_ARGS)
+
+        /* find min error code across processes */
+        TRACE_COMM(MPI_Allreduce)(&err, &status, 1, MPI_INT, MPI_MIN, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+        if (err == NC_NOERR) err = status;
+    }
+
+    if (err != NC_NOERR) {
+        if (newStr != NULL) ncmpii_free_NC_string(newStr);
+        return err;
     }
 
-    /* ncmpii_set_NC_string() will check for strlen(newname) > nchars error */
-    err = ncmpii_set_NC_string(varp->name, newname);
-    if (status == NC_NOERR) status = err;
+    assert(varp != NULL);
 
-    /* PnetCDF expects all processes use the same name, However, when names
-     * are not the same, only root's value is significant. Broadcast the
-     * new name at root to overwrite new names at other processes.
-     * (This API is collective if called in data mode)
-     */
-    TRACE_COMM(MPI_Bcast)(varp->name->cp, (int)varp->name->nchars, MPI_CHAR, 0,
-                          ncp->nciop->comm);
+    /* replace the old name with new name */
+    ncmpii_free_NC_string(varp->name);
+    varp->name = newStr;
 
-    /* Let root write the entire header to the file. Note that we cannot just
-     * update the variable name in its space occupied in the file header,
-     * because if the file space occupied by the name shrinks, all the metadata
-     * following it must be moved ahead.
-     */
-    err = ncmpii_write_header(ncp);
-    if (status == NC_NOERR) status = err;
+    if (! NC_indef(ncp)) { /* when file is in data mode */
+        /* Let root write the entire header to the file. Note that we cannot
+         * just update the variable name in its space occupied in the file
+         * header, because if the file space occupied by the name shrinks, all
+         * the metadata following it must be moved ahead.
+         */
+        err = ncmpii_write_header(ncp);
+        if (err != NC_NOERR) DEBUG_RETURN_ERROR(err)
+    }
 
-    return status;
+    return err;
 }
 
 /* some utility functions for debugging purpose */
 
 /*----< ncmpi_inq_varoffset() >-----------------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_inq_varoffset(int         ncid,
                     int         varid,
                     MPI_Offset *offset)
 {
-    int     status;
-    NC     *ncp;
-    NC_var *varp;
+    int     err;
+    NC     *ncp=NULL;
+    NC_var *varp=NULL;
 
-    status = ncmpii_NC_check_id(ncid, &ncp);
-    if (status != NC_NOERR) return status;
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
     /* using NC_GLOBAL in varid is illegal for this API. See
      * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
@@ -905,13 +1200,15 @@ ncmpi_inq_varoffset(int         ncid,
 #ifdef __DEBUG
 
 /*----< ncmpi_print_all_var_offsets() >---------------------------------------*/
+/* This is an independent subroutine */
 int
 ncmpi_print_all_var_offsets(int ncid) {
-    int i;
-    NC_var **vpp;
-    NC *ncp;
+    int i, err;
+    NC_var **vpp=NULL;
+    NC *ncp=NULL;
 
-    ncmpii_NC_check_id(ncid, &ncp);
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR || ncp == NULL) DEBUG_RETURN_ERROR(err)
 
     if (ncp->begin_var%1048576)
         printf("%s header size (ncp->begin_var)=%lld MB + %lld\n",
diff --git a/src/lib/vard.c b/src/lib/vard.c
index 8f79549..4abfb29 100644
--- a/src/lib/vard.c
+++ b/src/lib/vard.c
@@ -2,10 +2,10 @@
  *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: vard.c 2338 2016-03-03 18:49:31Z wkliao $ */
+/* $Id: vard.c 2588 2016-10-30 04:14:15Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -48,7 +48,7 @@ ncmpii_getput_vard(NC               *ncp,
     void *cbuf=NULL;
     int i, isderived, el_size, mpireturn, status=NC_NOERR, err=NC_NOERR;
     int buftype_is_contig=0, filetype_is_contig=1, need_swap=0, is_buf_swapped=0;
-    int filetype_size=0, buftype_size;
+    int filetype_size=0, buftype_size=0;
     MPI_Offset btnelems=0, bnelems=0, offset=0, orig_bufcount=bufcount;
     MPI_Status mpistatus;
     MPI_Datatype ptype, orig_buftype=buftype;
@@ -172,6 +172,7 @@ ncmpii_getput_vard(NC               *ncp,
             }
             buftype = ptype;
             bufcount *= bnelems;
+            buftype_size = el_size;
         }
     }
 
@@ -186,7 +187,7 @@ ncmpii_getput_vard(NC               *ncp,
 #endif
                 /* allocate cbuf and copy buf to cbuf, cbuf is to be freed */
                 cbuf = NCI_Malloc((size_t)filetype_size);
-                memcpy(cbuf, buf, filetype_size);
+                memcpy(cbuf, buf, (size_t)filetype_size);
             }
             /* perform array in-place byte swap on cbuf */
             ncmpii_in_swapn(cbuf, bnelems, ncmpix_len_nctype(varp->type));
@@ -233,30 +234,32 @@ err_check:
             TRACE_IO(MPI_File_write_at_all)(fh, offset, cbuf, (int)bufcount, buftype, &mpistatus);
             if (mpireturn != MPI_SUCCESS)
                 return ncmpii_handle_error(mpireturn, "MPI_File_write_at_all");
+            else
+                ncp->nciop->put_size += bufcount * buftype_size;
         }
         else { /* io_method == INDEP_IO */
             TRACE_IO(MPI_File_write_at)(fh, offset, cbuf, (int)bufcount, buftype, &mpistatus);
             if (mpireturn != MPI_SUCCESS)
                 return ncmpii_handle_error(mpireturn, "MPI_File_write_at");
+            else
+                ncp->nciop->put_size += bufcount * buftype_size;
         }
-        int put_size;
-        MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
-        ncp->nciop->put_size += put_size;
     }
     else {  /* rw_flag == READ_REQ */
         if (io_method == COLL_IO) {
             TRACE_IO(MPI_File_read_at_all)(fh, offset, cbuf, (int)bufcount, buftype, &mpistatus);
             if (mpireturn != MPI_SUCCESS)
                 return ncmpii_handle_error(mpireturn, "MPI_File_read_at_all");
+            else
+                ncp->nciop->get_size += bufcount * buftype_size;
         }
         else { /* io_method == INDEP_IO */
             TRACE_IO(MPI_File_read_at)(fh, offset, cbuf, (int)bufcount, buftype, &mpistatus);
             if (mpireturn != MPI_SUCCESS)
                 return ncmpii_handle_error(mpireturn, "MPI_File_read_at");
+            else
+                ncp->nciop->get_size += bufcount * buftype_size;
         }
-        int get_size;
-        MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
-        ncp->nciop->get_size += get_size;
     }
 
     /* No longer need to reset the file view, as the root's fileview includes
@@ -334,8 +337,8 @@ ncmpi_get_vard(int           ncid,
     NC     *ncp;
     NC_var *varp=NULL;
 
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARD,
-                                 1, 1, READ_REQ, INDEP_IO, &ncp, &varp);
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, buftype,
+                                 API_VARD, 1, 1, READ_REQ, INDEP_IO, &ncp, &varp);
     if (status != NC_NOERR) return status;
 
     return ncmpii_getput_vard(ncp, varp, filetype, buf, bufcount, buftype,
@@ -355,8 +358,8 @@ ncmpi_get_vard_all(int           ncid,
     NC     *ncp;
     NC_var *varp=NULL;
 
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARD,
-                                 1, 1, READ_REQ, COLL_IO, &ncp, &varp);
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, buftype,
+                                 API_VARD, 1, 1, READ_REQ, COLL_IO, &ncp, &varp);
     if (status != NC_NOERR) return status;
 
     return ncmpii_getput_vard(ncp, varp, filetype, buf, bufcount, buftype,
@@ -376,8 +379,8 @@ ncmpi_put_vard(int           ncid,
     NC     *ncp;
     NC_var *varp=NULL;
 
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARD,
-                                 1, 1, WRITE_REQ, INDEP_IO, &ncp, &varp);
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, buftype,
+                                 API_VARD, 1, 1, WRITE_REQ, INDEP_IO, &ncp, &varp);
     if (status != NC_NOERR) return status;
 
     return ncmpii_getput_vard(ncp, varp, filetype, (void*)buf, bufcount,
@@ -397,8 +400,8 @@ ncmpi_put_vard_all(int           ncid,
     NC     *ncp;
     NC_var *varp=NULL;
 
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARD,
-                                 1, 1, WRITE_REQ, COLL_IO, &ncp, &varp);
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, buftype,
+                                 API_VARD, 1, 1, WRITE_REQ, COLL_IO, &ncp, &varp);
     if (status != NC_NOERR) return status;
 
     return ncmpii_getput_vard(ncp, varp, filetype, (void*)buf, bufcount,
diff --git a/src/lib/varn.m4 b/src/lib/varn.m4
index 56123e7..4ddff5d 100644
--- a/src/lib/varn.m4
+++ b/src/lib/varn.m4
@@ -7,10 +7,10 @@ dnl
  *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: varn.m4 2320 2016-02-24 13:18:32Z wkliao $ */
+/* $Id: varn.m4 2559 2016-10-16 20:47:09Z wkliao $ */
 
 #if HAVE_CONFIG_H
-# include "ncconfig.h"
+# include <ncconfig.h>
 #endif
 
 #include <stdio.h>
@@ -27,6 +27,9 @@ dnl
 #include "ncmpidtype.h"
 #include "macro.h"
 
+include(`foreach.m4')
+include(`utils.m4')
+
 /* ncmpi_get/put_varn_<type>_<mode> API:
  *    type:   data type of I/O buffer, buf
  *    mode:   independent (<nond>) or collective (_all)
@@ -57,9 +60,7 @@ ncmpii_getput_varn(NC               *ncp,
                    int               rw_flag,
                    int               io_method);
 
-define(`CollIndep', `ifelse(`$1',`_all', `COLL_IO', `INDEP_IO')')dnl
 define(`BufConst',  `ifelse(`$1', `put', `const')')dnl
-define(`ReadWrite', `ifelse(`$1', `get', `READ_REQ', `WRITE_REQ')')dnl
 
 dnl
 dnl VARN_FLEXIBLE(ncid, varid, num starts, counts, buf, bufcount, buftype)
@@ -81,8 +82,9 @@ ncmpi_$1_varn$2(int                ncid,
     NC     *ncp;
     NC_var *varp=NULL;
 
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARN,
-                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, buftype,
+                                 API_VARN, 1,
+                                 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
     if (status != NC_NOERR) return status;
 
     return ncmpii_getput_varn(ncp, varp, num, starts, counts, (void*)buf,
@@ -114,8 +116,9 @@ ncmpi_$1_varn_$3$2(int                ncid,
     NC     *ncp;
     NC_var *varp=NULL;
 
-    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, API_VARN,
-                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, ITYPE2MPI($3),
+                                 API_VARN, 0,
+                                 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
     if (status != NC_NOERR) return status;
 
     /* set bufcount to -1 indicating non-flexible API */
@@ -123,59 +126,12 @@ ncmpi_$1_varn_$3$2(int                ncid,
                               -1, $5, ReadWrite($1), CollIndep($2));
 }
 ')dnl
-
-VARN(put,     , text,      char,               MPI_CHAR)
-VARN(put,     , schar,     schar,              MPI_SIGNED_CHAR)
-VARN(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARN(put,     , short,     short,              MPI_SHORT)
-VARN(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARN(put,     , int,       int,                MPI_INT)
-VARN(put,     , uint,      uint,               MPI_UNSIGNED)
-VARN(put,     , long,      long,               MPI_LONG)
-VARN(put,     , float,     float,              MPI_FLOAT)
-VARN(put,     , double,    double,             MPI_DOUBLE)
-VARN(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VARN(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARN(put, _all, text,      char,               MPI_CHAR)
-VARN(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VARN(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARN(put, _all, short,     short,              MPI_SHORT)
-VARN(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARN(put, _all, int,       int,                MPI_INT)
-VARN(put, _all, uint,      uint,               MPI_UNSIGNED)
-VARN(put, _all, long,      long,               MPI_LONG)
-VARN(put, _all, float,     float,              MPI_FLOAT)
-VARN(put, _all, double,    double,             MPI_DOUBLE)
-VARN(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VARN(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARN(get,     , text,      char,               MPI_CHAR)
-VARN(get,     , schar,     schar,              MPI_SIGNED_CHAR)
-VARN(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARN(get,     , short,     short,              MPI_SHORT)
-VARN(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARN(get,     , int,       int,                MPI_INT)
-VARN(get,     , uint,      uint,               MPI_UNSIGNED)
-VARN(get,     , long,      long,               MPI_LONG)
-VARN(get,     , float,     float,              MPI_FLOAT)
-VARN(get,     , double,    double,             MPI_DOUBLE)
-VARN(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
-VARN(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
-VARN(get, _all, text,      char,               MPI_CHAR)
-VARN(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
-VARN(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
-VARN(get, _all, short,     short,              MPI_SHORT)
-VARN(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
-VARN(get, _all, int,       int,                MPI_INT)
-VARN(get, _all, uint,      uint,               MPI_UNSIGNED)
-VARN(get, _all, long,      long,               MPI_LONG)
-VARN(get, _all, float,     float,              MPI_FLOAT)
-VARN(get, _all, double,    double,             MPI_DOUBLE)
-VARN(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
-VARN(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
-
+dnl
+foreach(`putget', (put, get),
+        `foreach(`collindep', (, _all),
+                 `foreach(`itype', (ITYPE_LIST),
+                          `VARN(putget,collindep,itype,FUNC2ITYPE(itype),ITYPE2MPI(itype))
+')')')
 
 /*----< ncmpii_getput_varn() >------------------------------------------------*/
 static int
@@ -205,6 +161,14 @@ ncmpii_getput_varn(NC               *ncp,
         DEBUG_ASSIGN_ERROR(status, NC_ENULLSTART)
         goto err_check;
     }
+    else { /* it is illegal for any starts[i] to be NULL */
+        for (i=0; i<num; i++) {
+            if (starts[i] == NULL) {
+                DEBUG_ASSIGN_ERROR(status, NC_ENULLSTART)
+                goto err_check;
+            }
+        }
+    }
 
     if (buftype == MPI_DATATYPE_NULL) {
         /* In this case, bufcount is ignored and will be recalculated to match
@@ -217,9 +181,13 @@ ncmpii_getput_varn(NC               *ncp,
             bufcount = 0;
             for (j=0; j<num; j++) {
                 MPI_Offset bufcount_j = 1;
+                if (counts[i] == NULL) {
+                    DEBUG_ASSIGN_ERROR(status, NC_ENULLCOUNT)
+                    goto err_check;
+                }
                 for (i=0; i<varp->ndims; i++) {
                     if (counts[j][i] < 0) { /* no negative counts[][] */
-                        DEBUG_ASSIGN_ERROR(err, NC_ENEGATIVECNT)
+                        DEBUG_ASSIGN_ERROR(status, NC_ENEGATIVECNT)
                         goto err_check;
                     }
                     bufcount_j *= counts[j][i];
diff --git a/src/libcxx/ncmpiGroup.cpp b/src/libcxx/ncmpiGroup.cpp
index 8759e25..b776d9d 100644
--- a/src/libcxx/ncmpiGroup.cpp
+++ b/src/libcxx/ncmpiGroup.cpp
@@ -46,7 +46,8 @@ NcmpiGroup::~NcmpiGroup()
 
 // Constructor generates a null object.
 NcmpiGroup::NcmpiGroup() :
-  nullObject(true)
+  nullObject(true),
+  myId(-1)
 {}
 
    
@@ -1370,6 +1371,7 @@ NcmpiCompoundType NcmpiGroup::addCompoundType(const string& name, MPI_Offset siz
 }
   
   
+#if 0
 // Get the collection of coordinate variables.
 map<string,NcmpiGroup> NcmpiGroup::getCoordVars(NcmpiGroup::Location location) const {
   map<string,NcmpiGroup> coordVars;
@@ -1454,3 +1456,4 @@ void NcmpiGroup::getCoordVar(string& coordVarName, NcmpiDim& ncmpiDim, NcmpiVar&
   }
 
 }
+#endif
diff --git a/src/libcxx/ncmpiGroup.h b/src/libcxx/ncmpiGroup.h
index 311b101..84c19c4 100644
--- a/src/libcxx/ncmpiGroup.h
+++ b/src/libcxx/ncmpiGroup.h
@@ -566,8 +566,8 @@ namespace PnetCDF
       
       \param location Enumeration type controlling the groups to search.
       \return         The NcmpiVar dimension variable. If no valid object is found , a \ref NcmpiVar::isNull "null node" is returned.
-    */
     std::map<std::string,NcmpiGroup> getCoordVars(NcmpiGroup::Location location=Current) const;
+    */
 
     /*! 
       Gets the NcmpiDim and NcmpiVar object pair for a named coordinate variable.
@@ -577,8 +577,8 @@ namespace PnetCDF
       group and optionally in the parent and child group and returns the first instance found.
       \param location Enumeration type controlling the groups to search.
       \return         The set of names of dimension variables. 
-    */
     void getCoordVar(std::string& coordVarName, NcmpiDim& ncmpiDim, NcmpiVar& ncmpiVar, NcmpiGroup::Location location=Current) const;
+    */
 
 
   protected:
diff --git a/src/libcxx/ncmpiVarAtt.cpp b/src/libcxx/ncmpiVarAtt.cpp
index 902a782..7af3546 100644
--- a/src/libcxx/ncmpiVarAtt.cpp
+++ b/src/libcxx/ncmpiVarAtt.cpp
@@ -52,9 +52,8 @@ NcmpiVarAtt::NcmpiVarAtt(const NcmpiGroup& grp, const NcmpiVar& ncmpiVar, const
   varId = ncmpiVar.getId();
   // get the name of this attribute
   char attName[NC_MAX_NAME+1];
-  ncmpiCheck(ncmpi_inq_attname(groupId,varId, index, attName),__FILE__,__LINE__);
   ncmpiCheck(ncmpi_inq_attname(groupId,varId,index,attName),__FILE__,__LINE__);
-  myName = attName;
+  myName = std::string(attName);
 }
 
 // Returns the NcmpiVar parent object.
diff --git a/src/libf/Makefile.in b/src/libf/Makefile.in
index e2dfeee..3b467b4 100644
--- a/src/libf/Makefile.in
+++ b/src/libf/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2285 2015-12-30 20:48:25Z wkliao $
+# $Id: Makefile.in 2584 2016-10-27 18:53:05Z wkliao $
 #
 # @configure_input@
 
@@ -26,6 +26,7 @@ ld_netcdf = -L../lib -lpnetcdf
 UTIL_SRCS = issyserrf.c \
 	nfxutil.c \
 	xstrerrorf.c \
+	xstrerrnof.c \
 	xinq_libversf.c
 
 C2F_SRCS = createf.c \
@@ -355,7 +356,7 @@ C2F_SRCS = createf.c \
 
 LIB_CSRCS = $(C2F_SRCS) $(UTIL_SRCS)
 
-LIB_FSRCS = strerrorf.f inq_libversf.f
+LIB_FSRCS = strerrorf.f strerrnof.f inq_libversf.f
 
 PACKING_LIST = $(LIB_FSRCS) \
 	       nfconfig_inc.in \
diff --git a/src/libf/buildiface b/src/libf/buildiface
index 22eade4..32062d9 100755
--- a/src/libf/buildiface
+++ b/src/libf/buildiface
@@ -583,10 +583,11 @@ if ($build_prototypes) {
  *  (C) 2003 by Argonne National Laboratory and Northwestern University.\
  *      See COPYRIGHT in top-level directory.\
  *\
- * This file is automatically generated by ./buildiface $arg_string\
+ * This file is automatically generated by command:\
+ *     ./buildiface $arg_string\
  * DO NOT EDIT\
  */\
-/* Prototypes for Fortran Interface Functions */
+/* Prototypes for Fortran Interface Functions */\
 \n";
 }
 
@@ -768,9 +769,13 @@ sub print_copyright {
  *  (C) 2003 by Argonne National Laboratory and Northwestern University.\
  *      See COPYRIGHT in top-level directory.\
  *\
- * This file is automatically generated by ./buildiface $arg_string\
+ * This file is automatically generated by command:\
+ *     ./buildiface $arg_string\
  * DO NOT EDIT\
  */\
+#ifdef __GNUC__\
+#pragma GCC diagnostic ignored \"-Wunused-parameter\"\
+#endif\
 #include \"${header_file}\"\n\n";
 }
 
@@ -1742,7 +1747,7 @@ sub blankpad_ctof {
     my $cvar = $outvar; 
     $cvar =~ s/^v/p/;
     print $OUTFD "
-    {
+    if (ierr == NC_NOERR) {
         char *p = $outvar, *pc=$cvar;
         while (*pc) {*p++ = *pc++;}
         while ((p-$outvar) < $strlen) { *p++ = ' '; }
@@ -1812,13 +1817,13 @@ sub addnull_ftoc {
     $strlen = "v$count";
     $strlen =~ s/^v/d/;
     print $OUTFD "\
-    {char *p = v$count + $strlen - 1;
-     int  li;
-        while (*p == ' ' && p > v$count) p--;
+    {
+        char *p = v$count + $strlen - 1; /* point to the end of string v$count */
+        while (*p == ' ' && p > v$count) p--; /* find the last non-blank */
         p++;
-        p$count = (char *)$malloc( (size_t)(p-v$count) + 1 );
-        for (li=0; li<(p-v$count); li++) { p$count\[li\] = v$count\[li\]; }
-        p$count\[li\] = 0; 
+        p$count = (char *) $malloc((size_t)(p-v$count) + 1);
+        memcpy(p$count, v$count, p-v$count);
+        p$count\[p-v$count\] = 0; 
     }
 ";
     $clean_up .= "    $free( p$count );\n";
@@ -2299,7 +2304,8 @@ if ($write_mpif) {
     print MPIFFD "$cchar      See COPYRIGHT in top-level directory.\n";
     print MPIFFD "$cchar      \n";
     print MPIFFD "$cchar      DO NOT EDIT\n";
-    print MPIFFD "$cchar      This file created by ./buildiface $arg_string\n";
+    print MPIFFD "$cchar      This file created by command:\n";
+    print MPIFFD "$cchar          ./buildiface $arg_string\n";
     print MPIFFD "$cchar      \n";
     #
     # Status elements
@@ -3081,7 +3087,8 @@ MPIR_Comm_delete_attr_f77_proxy(
  *  (C) 2003 by Argonne National Laboratory and Northwestern University.
  *      See COPYRIGHT in top-level directory.
  *
- * This file is automatically generated by ./buildiface 
+ * This file is automatically generated by command:\
+ *     ./buildiface $arg_string\
  * DO NOT EDIT
  */
 #include \"mpi_fortimpl.h\"
@@ -3140,7 +3147,8 @@ print $OUTFD "\
  *  (C) 2003 by Argonne National Laboratory and Northwestern University.
  *      See COPYRIGHT in top-level directory.
  *
- * This file is automatically generated by ./buildiface 
+ * This file is automatically generated by command:\
+ *     ./buildiface $arg_string\
  * DO NOT EDIT
  */
 #include \"mpi_fortimpl.h\"
diff --git a/src/libf/defs b/src/libf/defs
index 9a5f8d4..76fa08f 100644
--- a/src/libf/defs
+++ b/src/libf/defs
@@ -2,7 +2,7 @@
 #  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 #  See COPYRIGHT notice in top-level directory.
 #
-# $Id: defs 2071 2015-08-11 04:39:53Z wkliao $
+# $Id: defs 2584 2016-10-27 18:53:05Z wkliao $
 
 $routine_prefix = "ncmpi_";
 $routine_pattern = "[a-z0-9_]*";
@@ -679,8 +679,8 @@ $returnType   = "int";
 		'inq_dimname-2'		=> 'in:IntIndexIn',
 		'inq_dimname-3'		=> 'out:blankpad',
 	'inq_unlimdim' => 2,
-		'inq_unlimdim-2'	=> 'out:IntIndex',
-	'inq_var' => '2:3:6',
+		'inq_unlimdim-2'	=> 'out:IntDimIndex',
+	'inq_var' => '2:6:3',
 		'inq_var-2'		=> 'in:IntIndexIn',
 		'inq_var-3'		=> 'out:blankpad',
 		'inq_var-6'		=> 'out:reorderIntArrOut',
@@ -2003,7 +2003,7 @@ $declarg{'bput_varm_int8-7'}		= 'const long long *';
 #
 sub reorderOffsetArr_in_decl {
     my $count = $_[0];
-    print $OUTFD "    MPI_Offset *l$count = NULL;\n";
+    print $OUTFD "    MPI_Offset *l$count=NULL;\n";
 }
 sub reorderOffsetArr_ftoc {
     my $count = $_[0];
@@ -2011,24 +2011,20 @@ sub reorderOffsetArr_ftoc {
     # call a function of some of the other arguments to get the array size
     if ($Array_size) {
         print $OUTFD "
-    int ndims;
+    int ndims, li;
     ierr = ncmpi_inq_varndims(*v1, l2, &ndims); /* get number of dimensions */
     if (ierr != NC_NOERR) return ierr;
 
-    if (ndims > 0) {
-        int li;
-        l$count = (MPI_Offset*) $malloc((size_t)ndims * sizeof(MPI_Offset));
-        for (li=0; li<ndims; li++) /* convert Fortran order to C order */
-            l$count\[li\] = v$count\[ndims-1-li\] - 1; /* convert 1-based to 0-based */
-    }\n";
+    l$count = (MPI_Offset*) $malloc((size_t)ndims * sizeof(MPI_Offset));
+    for (li=0; li<ndims; li++) /* convert Fortran order to C order */
+        l$count\[li\] = v$count\[ndims-1-li\] - 1; /* convert 1-based to 0-based */
+    \n";
     } else {
         print $OUTFD "
-    if (ndims > 0) {
-        int li;
-        l$count = (MPI_Offset*) $malloc((size_t)ndims * sizeof(MPI_Offset));
-        for (li=0; li<ndims; li++) /* convert Fortran order to C order */
-            l$count\[li\] = v$count\[ndims-1-li\];
-    }\n";
+    l$count = (MPI_Offset*) $malloc((size_t)ndims * sizeof(MPI_Offset));
+    for (li=0; li<ndims; li++) /* convert Fortran order to C order */
+        l$count\[li\] = v$count\[ndims-1-li\];
+    \n";
     }
 }
 sub reorderOffsetArr_in_arg {
@@ -2039,8 +2035,7 @@ sub reorderOffsetArr_in_arg {
 sub reorderOffsetArr_in_ctof {
     my $lname = $_[0];
     my $vname = $_[1];
-    print $OUTFD "
-    if ($lname) { $free($lname); }
+    print $OUTFD "    $free($lname);
 ";
 }
 
@@ -2055,34 +2050,33 @@ sub reorderOffsetArr_in_ctof {
 #
 sub reorderOffsetArr1DTo2D_in_decl {
     my $count = $_[0];
-    print $OUTFD "    MPI_Offset **l$count = NULL;\n";
+    print $OUTFD "    MPI_Offset **l$count=NULL;\n";
 }
 sub reorderOffsetArr1DTo2D_ftoc {
     my $count = $_[0];
     if ($Array_size) {
         print $OUTFD "
-    int ndims;
+    int ndims, li, lj;
     ierr = ncmpi_inq_varndims(*v1, l2, &ndims); /* get number of dimensions */
     if (ierr != NC_NOERR) return ierr;\n"
     }
     print $OUTFD "
-    if (ndims > 0) {
-        int li, lj;
-        size_t len = (size_t)*v3;
-        l$count    = (MPI_Offset**) $malloc(len * sizeof(MPI_Offset*));
-        l$count\[0\] = (MPI_Offset*)  $malloc(len * (size_t)ndims * sizeof(MPI_Offset));
-        for (lj=1; lj<*v3; lj++)
-            l$count\[lj\] = l$count\[lj-1\] + ndims;
-        for (lj=0; lj<*v3; lj++)
-            for (li=0; li<ndims; li++) /* convert Fortran order to C order */";
+    if (*v3 > 0) {
+        l$count    = (MPI_Offset**) $malloc((size_t)*v3 * sizeof(MPI_Offset*));
+        l$count\[0\] = (MPI_Offset*)  $malloc((size_t)*v3 * (size_t)ndims * sizeof(MPI_Offset));
+    }
+    for (lj=1; lj<*v3; lj++)
+        l$count\[lj\] = l$count\[lj-1\] + ndims;
+    for (lj=0; lj<*v3; lj++)
+        for (li=0; li<ndims; li++) /* convert Fortran order to C order */";
     if ($Array_size) {
         print $OUTFD "
-                l$count\[lj\]\[li\] = v$count\[lj*ndims + ndims-1-li\] - 1; /* convert 1-based to 0-based */
-    }\n";
+            l$count\[lj\]\[li\] = v$count\[lj*ndims + ndims-1-li\] - 1; /* convert 1-based to 0-based */
+    \n";
     } else {
         print $OUTFD "
-                l$count\[lj\]\[li\] = v$count\[lj*ndims + ndims-1-li\];
-    }\n";
+            l$count\[lj\]\[li\] = v$count\[lj*ndims + ndims-1-li\];
+    \n";
     }
 }
 sub reorderOffsetArr1DTo2D_in_arg {
@@ -2094,7 +2088,10 @@ sub reorderOffsetArr1DTo2D_in_ctof {
     my $lname = $_[0];
     my $vname = $_[1];
     print $OUTFD "
-    if ($lname) { $free($lname\[0\]); $free($lname); }
+    if (*v3 > 0) {
+       $free($lname\[0\]);
+       $free($lname);
+    }
 ";
 }
 
@@ -2109,7 +2106,7 @@ sub reorderOffsetArr1DTo2D_in_ctof {
 #
 sub reorderIntArr_in_decl {
     my $count = $_[0];
-    print $OUTFD "    int *l$count=NULL;\n";
+    print $OUTFD "    int *l$count;\n";
 }
 sub reorderIntArr_ftoc {
     my $count = $_[0];
@@ -2118,17 +2115,15 @@ sub reorderIntArr_ftoc {
     # Always copy and invert order
     if ($Array_size) {
         print $OUTFD "
-    int ndims;
+    int ndims, li;
     ierr = ncmpi_inq_varndims(*v1, l2, &ndims); /* get number of dimensions */
     if (ierr != NC_NOERR) return ierr;\n"
     }
     print $OUTFD "
-    if (ndims > 0) {
-        int li;
-        l$count = (int*) $malloc((size_t)ndims * sizeof(int));
-        for (li=0; li<ndims; li++) /* convert Fortran order to C order */
-            l$count\[li\] = v$count\[ndims-1-li\];
-    }\n";
+    l$count = (int*) $malloc((size_t)ndims * sizeof(int));
+    for (li=0; li<ndims; li++) /* convert Fortran order to C order */
+        l$count\[li\] = v$count\[ndims-1-li\];
+    \n";
     $clean_up .= "    $free(l$count);\n";
 }
 sub reorderIntArr_in_arg {
@@ -2153,7 +2148,7 @@ sub reorderIntArr_in_ctof {
 #
 sub reorderIntArrOut_out_decl {
     my $count = $_[0];
-    print $OUTFD "    int *l$count=NULL;\n";
+    print $OUTFD "    int *l$count;\n";
 }
 sub reorderIntArrOut_out_ftoc {
     my $count = $_[0];
@@ -2161,13 +2156,12 @@ sub reorderIntArrOut_out_ftoc {
     # call a function of some of the other arguments to get the array size
     # Always copy and invert order
     print $OUTFD "
-    int ndims;
+    int ndims, li;
     ierr = ncmpi_inq_varndims(*v1, l2, &ndims); /* get number of dimensions */
     if (ierr != NC_NOERR) return ierr;
 
-    if (ndims > 0) {
-        l$count = (int*) $malloc((size_t)ndims * sizeof(int));
-    }\n";
+    l$count = (int*) $malloc((size_t)ndims * sizeof(int));
+    \n";
 }
 sub reorderIntArrOut_out_arg {
     my $count = $_[0];
@@ -2178,12 +2172,11 @@ sub reorderIntArrOut_ctof {
     my $lname = $_[0];
     my $vname = $_[1];
     print $OUTFD "
-    if (ndims > 0) {
-        int li;
+    if (ierr == NC_NOERR) {
         for (li=0; li<ndims; li++) /* convert C order to Fortran order */
             v$count\[li\] = l$count\[ndims-1-li\] + 1; /* convert from 0-based to 1-based */
-        $free($lname);
-    }\n";
+    }
+    $free($lname);\n";
 }
 
 # -------------------------------------------------------------------------
@@ -2409,6 +2402,7 @@ sub blankpad_out_ftoc {
 # ---------------------------------------------------------------------------
 # Functions to add routines that need special handling
 $ExtraRoutines[$#ExtraRoutines+1] = "ncfxstrerror";
+$ExtraRoutines[$#ExtraRoutines+1] = "ncfxstrerrno";
 $ExtraRoutines[$#ExtraRoutines+1] = "ncfxutil";
 $ExtraRoutines[$#ExtraRoutines+1] = "ncfxinqlibvers";
 $ExtraRoutines[$#ExtraRoutines+1] = "ncfissyserr";
@@ -2426,13 +2420,34 @@ sub ncfxstrerror {
     &print_args( $OUTFD, $args, 0, "xstrerror" );
     print $OUTFD "{
     const char *p = ncmpi_strerror( *v1 );
-    int i;
+    size_t len = strlen(p);
     /* d2 is the length of the string passed into the routine */
-    for (i=0; i<d2 && *p; i++) {
-        v2[i] = *p++;
-    }
+    if (len > d2) len = d2;  /* MIN(len, d2) */
+    memcpy(v2, p, len);
     /* Blank pad */
-    for (; i<d2; i++) v2[i] = ' ';
+    if (len < d2) memset(v2+len, ' ', d2-len);
+    return 0;
+}\n";
+    close ($OUTFD);
+}
+
+sub ncfxstrerrno {
+    $OUTFD = "NCFXSTRERRNOFD";
+    open( $OUTFD, ">xstrerrnof.c" ) || die "Cannot open xstrerrnof.c\n";
+    $out_prefix = "nfmpi_";
+    $files[$#files+1] = "xstrerrnof.c";
+    $args = "int *, char *";
+    &print_header( "ncfmpi_xstrerrno", "xstrerrno", $args );
+    &print_routine_type_decl( $OUTFD, "xstrerrno" );
+    &print_args( $OUTFD, $args, 0, "xstrerrno" );
+    print $OUTFD "{
+    const char *p = ncmpi_strerrno( *v1 );
+    size_t len = strlen(p);
+    /* d2 is the length of the string passed into the routine */
+    if (len > d2) len = d2;  /* MIN(len, d2) */
+    memcpy(v2, p, len);
+    /* Blank pad */
+    if (len < d2) memset(v2+len, ' ', d2-len);
     return 0;
 }\n";
     close ($OUTFD);
@@ -2466,13 +2481,12 @@ sub ncfxinqlibvers {
     &print_args( $OUTFD, $args, 0, "xinq_libvers" );
     print $OUTFD "{
     const char *p = ncmpi_inq_libvers();
-    int i;
+    size_t len = strlen(p);
     /* d1 is the length of the string passed into the routine */
-    for (i=0; i<d1 && *p; i++) {
-        v1[i] = *p++;
-    }
+    if (len > d1) len = d1;  /* MIN(len, d1) */
+    memcpy(v1, p, len);
     /* Blank pad */
-    for (; i<d1; i++) v1[i] = ' ';
+    if (len < d1) memset(v1+len, ' ', d1-len);
     return 0;
 }\n";
     close ($OUTFD);
diff --git a/src/libf/mpinetcdf_impl.h b/src/libf/mpinetcdf_impl.h
index d9ffa98..51786fa 100644
--- a/src/libf/mpinetcdf_impl.h
+++ b/src/libf/mpinetcdf_impl.h
@@ -3,7 +3,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *      See COPYRIGHT in top-level directory.
  */
-/* $Id: mpinetcdf_impl.h 2104 2015-09-18 23:36:19Z wkliao $ */
+/* $Id: mpinetcdf_impl.h 2584 2016-10-27 18:53:05Z wkliao $ */
 
 #ifndef MPINETCDF_IMPL_H
 #define MPINETCDF_IMPL_H
@@ -13,6 +13,7 @@
 #endif
 
 #include <stdlib.h>
+#include <string.h> /* memcpy(), memset() */
 #include <pnetcdf.h>
 
 /* Support Windows extension to specify calling convention */
@@ -61,6 +62,7 @@
 int ncmpixVardim( int, int );
 
 extern FORTRAN_API int FORT_CALL nfmpi_xstrerror_ ( MPI_Fint *v1, char *v2 FORT_MIXED_LEN(d2) FORT_END_LEN(d2) );
+extern FORTRAN_API int FORT_CALL nfmpi_xstrerrno_ ( MPI_Fint *v1, char *v2 FORT_MIXED_LEN(d2) FORT_END_LEN(d2) );
 extern FORTRAN_API int FORT_CALL nfmpi_xinq_libvers_ ( char *v1 FORT_MIXED_LEN(d1) FORT_END_LEN(d1) );
 extern FORTRAN_API int FORT_CALL nfmpi_issyserr_ ( MPI_Fint *v1 );
 /* Define the internal values needed for Fortran support */
diff --git a/src/libf/pnetcdf.inc.in b/src/libf/pnetcdf.inc.in
index 99891c5..f400748 100644
--- a/src/libf/pnetcdf.inc.in
+++ b/src/libf/pnetcdf.inc.in
@@ -1,4 +1,10 @@
 !
+! Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+! See COPYRIGHT notice in top-level directory.
+!
+! @configure_input@
+
+!
 ! pnetcdf fortran defines
 !
 
@@ -14,6 +20,19 @@
       parameter (PNETCDF_VERSION_SUB   = @PNETCDF_VERSION_SUB@)
 
 !
+! list of PnetCDF options enabled/disabled at configure time
+!
+      integer PNETCDF_ERANGE_FILL
+      integer PNETCDF_SUBFILING
+      integer PNETCDF_RELAX_COORD_BOUND
+      integer PNETCDF_DEBUG_MODE
+
+      parameter (PNETCDF_ERANGE_FILL       = @ENABLE_ERANGE_FILL@)
+      parameter (PNETCDF_SUBFILING         = @ENABLE_SUBFILING@)
+      parameter (PNETCDF_RELAX_COORD_BOUND = @RELAX_COORD_BOUND@)
+      parameter (PNETCDF_DEBUG_MODE        = @PNETCDF_DEBUG@)
+
+!
 ! external netcdf data types: (must conform with netCDF release)
 !
       integer nf_byte
@@ -369,6 +388,8 @@
       integer NF_ESTRICTCDF2
       integer NF_ENOTRECVAR
       integer NF_ENOTFILL
+      integer NF_EINVAL_OMODE
+      integer NF_EPENDING
 
       integer NF_EMULTIDEFINE
       integer NF_EMULTIDEFINE_OMODE,      NF_ECMODE
@@ -393,6 +414,7 @@
       integer NF_EMULTIDEFINE_FILL_MODE
       integer NF_EMULTIDEFINE_VAR_FILL_MODE
       integer NF_EMULTIDEFINE_VAR_FILL_VALUE
+      integer NF_EMULTIDEFINE_CMODE
 
 !
 ! PnetCDF error codes start from -201
@@ -424,19 +446,21 @@
       PARAMETER (NF_EQUOTA                  = -225)   ! Quota exceeded
       PARAMETER (NF_ENULLSTART              = -226)   ! argument start is a NULL pointer
       PARAMETER (NF_ENULLCOUNT              = -227)   ! argument count is a NULL pointer
-      PARAMETER (NF_EINVAL_CMODE            = -228)   ! Invalid file create mode, cannot have both NC_64BIT_OFFSET & NC_64BIT_DATA
+      PARAMETER (NF_EINVAL_CMODE            = -228)   ! Invalid file create mode
       PARAMETER (NF_ETYPESIZE               = -229)   ! MPI derived data type size error (bigger than the variable size)
       PARAMETER (NF_ETYPE_MISMATCH          = -230)   ! element type of the MPI derived data type mismatches the variable type
       PARAMETER (NF_ETYPESIZE_MISMATCH      = -231)   ! file type size mismatches buffer type size
       PARAMETER (NF_ESTRICTCDF2             = -232)   ! Attempting CDF-5 operation on CDF-2 file
       PARAMETER (NF_ENOTRECVAR              = -233)   ! Attempting operation only for record variables
       PARAMETER (NF_ENOTFILL                = -234)   ! Attempting to fill a variable when its fill mode is off
+      PARAMETER (NF_EINVAL_OMODE            = -235)   ! Invalid file open mode
+      PARAMETER (NF_EPENDING                = -236)   ! Pending nonblocking request is found at file close
 
 !
 ! PnetCDF header inconsistency errors start from -250
 !
       PARAMETER (NF_EMULTIDEFINE            = -250)   ! NC definitions on multiprocesses conflict
-      PARAMETER (NF_EMULTIDEFINE_OMODE      = -251)   ! file create/open modes are inconsistent
+      PARAMETER (NF_EMULTIDEFINE_OMODE      = -251)   ! inconsistent file open modes
       PARAMETER (NF_EMULTIDEFINE_DIM_NUM    = -252)   ! inconsistent number of dimensions
       PARAMETER (NF_EMULTIDEFINE_DIM_SIZE   = -253)   ! inconsistent size of dimension
       PARAMETER (NF_EMULTIDEFINE_DIM_NAME   = -254)   ! inconsistent dimension names
@@ -458,6 +482,7 @@
       PARAMETER (NF_EMULTIDEFINE_FILL_MODE  = -270)   !  inconsistent dataset fill mode
       PARAMETER (NF_EMULTIDEFINE_VAR_FILL_MODE  = -271) ! inconsistent variable fill mode
       PARAMETER (NF_EMULTIDEFINE_VAR_FILL_VALUE = -272) ! inconsistent variable fill value
+      PARAMETER (NF_EMULTIDEFINE_CMODE      = -273)   ! inconsistent file create modes
 
       PARAMETER(NF_ECMODE                  =NF_EMULTIDEFINE_OMODE)
       PARAMETER(NF_EDIMS_NELEMS_MULTIDEFINE=NF_EMULTIDEFINE_DIM_NUM)
@@ -709,9 +734,11 @@
 !
       character*80  nfmpi_inq_libvers
       character*80  nfmpi_strerror
+      character*80  nfmpi_strerrno
 
       external      nfmpi_inq_libvers
       external      nfmpi_strerror
+      external      nfmpi_strerrno
 
       logical       nfmpi_issyserr
       external      nfmpi_issyserr
@@ -882,23 +909,23 @@
 !
 ! entire variable put/get routines:
 !
-      integer  nfmpi_put_var
-      integer  nfmpi_put_var_text
-      integer  nfmpi_put_var_int1
-      integer  nfmpi_put_var_int2
-      integer  nfmpi_put_var_int
-      integer  nfmpi_put_var_real
-      integer  nfmpi_put_var_double
-      integer  nfmpi_put_var_int8
-
-      external nfmpi_put_var
-      external nfmpi_put_var_text
-      external nfmpi_put_var_int1
-      external nfmpi_put_var_int2
-      external nfmpi_put_var_int
-      external nfmpi_put_var_real
-      external nfmpi_put_var_double
-      external nfmpi_put_var_int8
+      integer  nfmpi_put_var,        nfmpi_put_var_all
+      integer  nfmpi_put_var_text,   nfmpi_put_var_text_all
+      integer  nfmpi_put_var_int1,   nfmpi_put_var_int1_all
+      integer  nfmpi_put_var_int2,   nfmpi_put_var_int2_all
+      integer  nfmpi_put_var_int,    nfmpi_put_var_int_all
+      integer  nfmpi_put_var_real,   nfmpi_put_var_real_all
+      integer  nfmpi_put_var_double, nfmpi_put_var_double_all
+      integer  nfmpi_put_var_int8,   nfmpi_put_var_int8_all
+
+      external nfmpi_put_var,        nfmpi_put_var_all
+      external nfmpi_put_var_text,   nfmpi_put_var_text_all
+      external nfmpi_put_var_int1,   nfmpi_put_var_int1_all
+      external nfmpi_put_var_int2,   nfmpi_put_var_int2_all
+      external nfmpi_put_var_int,    nfmpi_put_var_int_all
+      external nfmpi_put_var_real,   nfmpi_put_var_real_all
+      external nfmpi_put_var_double, nfmpi_put_var_double_all
+      external nfmpi_put_var_int8,   nfmpi_put_var_int8_all
 
       integer  nfmpi_get_var,        nfmpi_get_var_all
       integer  nfmpi_get_var_text,   nfmpi_get_var_text_all
diff --git a/src/libf/strerrnof.f b/src/libf/strerrnof.f
new file mode 100644
index 0000000..05c0667
--- /dev/null
+++ b/src/libf/strerrnof.f
@@ -0,0 +1,10 @@
+      character *80 function nfmpi_strerrno( err )
+      integer err, ierr
+      character *(80) tmpstr
+
+      integer nfmpi_xstrerrno
+      external nfmpi_xstrerrno
+
+      ierr = nfmpi_xstrerrno( err, tmpstr )
+      nfmpi_strerrno = tmpstr
+      end
diff --git a/src/libf90/Makefile.in b/src/libf90/Makefile.in
index f90bbd8..7b398f5 100644
--- a/src/libf90/Makefile.in
+++ b/src/libf90/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2318 2016-02-04 00:18:26Z wkliao $
+# $Id: Makefile.in 2597 2016-11-04 22:12:08Z wkliao $
 #
 # @configure_input@
 
@@ -60,6 +60,7 @@ PACKING_LIST = $(F90_SRCS) \
 GARBAGE		= $(PNETCDF_MOD) $(M4_SRCS:.m4=.f90)
 DIST_GARBAGE	= pnetcdf.f90 api.f90 nfmpi_constants.f90
 
+# When compiling pnetcdf.o, it also produce pnetcdf.mod
 %.mod: %.f90 $(SRCS)
 	$(COMPILE.f90) $<
 
diff --git a/src/libf90/api.f90.in b/src/libf90/api.f90.in
index 192bab6..a1e037e 100644
--- a/src/libf90/api.f90.in
+++ b/src/libf90/api.f90.in
@@ -2,8 +2,9 @@
 !  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: api.f90.in 2318 2016-02-04 00:18:26Z wkliao $
+! $Id: api.f90.in 2615 2016-11-13 23:58:41Z wkliao $
 !
+! @configure_input@
 
 !
 ! miscellaneous subroutines:
@@ -16,6 +17,10 @@ INTERFACE
                             INTEGER,                       INTENT(IN)  :: ncerr
     END FUNCTION   nfmpi_strerror
 
+    character(LEN=80) FUNCTION nfmpi_strerrno(ncerr)
+                            INTEGER,                       INTENT(IN)  :: ncerr
+    END FUNCTION   nfmpi_strerrno
+
     logical        FUNCTION nfmpi_issyserr(ncerr)
                             INTEGER,                       INTENT(IN)  :: ncerr
     END FUNCTION   nfmpi_issyserr
diff --git a/src/libf90/attributes.f90 b/src/libf90/attributes.f90
index 68a67f9..09e274e 100644
--- a/src/libf90/attributes.f90
+++ b/src/libf90/attributes.f90
@@ -2,7 +2,7 @@
 !  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: attributes.f90 1525 2013-12-14 17:17:42Z wkliao $
+! $Id: attributes.f90 2519 2016-10-06 00:41:33Z wkliao $
 !
 ! This file is taken from netcdf_attributes.f90 with changes for PnetCDF use
 !  
@@ -48,11 +48,12 @@
   end function nf90mpi_inq_attname
   ! -------
   function nf90mpi_inquire_attribute(ncid, varid, name, xtype, len, attnum)
-    integer,             intent( in)           :: ncid, varid
-    character (len = *), intent( in)           :: name
-    integer,             intent(out), optional :: xtype, attnum
-    integer (kind=MPI_OFFSET_KIND), intent(out), optional :: len
+    integer,                                  intent( in) :: ncid, varid
+    character (len = *),                      intent( in) :: name
+    integer,                        optional, intent(out) :: xtype, attnum
+    integer (kind=MPI_OFFSET_KIND), optional, intent(out) :: len
     integer                                    :: nf90mpi_inquire_attribute
+
     integer                                    :: local_xtype
     integer (kind=MPI_OFFSET_KIND)             :: local_len
 
diff --git a/src/libf90/file.f90 b/src/libf90/file.f90
index 53f7267..b61106e 100644
--- a/src/libf90/file.f90
+++ b/src/libf90/file.f90
@@ -2,7 +2,7 @@
 !  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: file.f90 2013 2015-02-18 17:14:26Z wkliao $
+! $Id: file.f90 2584 2016-10-27 18:53:05Z wkliao $
 !
 ! This file is taken from netcdf_file.f90 with changes for PnetCDF use
 !  
@@ -14,7 +14,7 @@
 ! This file contains the netcdf file functions that are shared by
 ! netcdf-3 and netcdf-4.
 
-! $Id: file.f90 2013 2015-02-18 17:14:26Z wkliao $
+! $Id: file.f90 2584 2016-10-27 18:53:05Z wkliao $
 ! -------
 function nf90mpi_inq_libvers()
   character(len = 80) :: nf90mpi_inq_libvers
@@ -29,6 +29,13 @@ function nf90mpi_strerror(ncerr)
   nf90mpi_strerror = nfmpi_strerror(ncerr)
 end function nf90mpi_strerror
 ! -------
+function nf90mpi_strerrno(ncerr)
+  integer, intent( in) :: ncerr
+  character(len = 80)  :: nf90mpi_strerrno
+
+  nf90mpi_strerrno = nfmpi_strerrno(ncerr)
+end function nf90mpi_strerrno
+! -------
 !
 ! File level control routines:
 !
@@ -128,8 +135,8 @@ end function nf90mpi_close
 ! -------
 function nf90mpi_delete(name, mpi_info)
   character(len = *), intent( in) :: name
-  integer                         :: nf90mpi_delete
   integer,            intent( in) :: mpi_info
+  integer                         :: nf90mpi_delete
 
   nf90mpi_delete = nfmpi_delete(name, mpi_info)
 end function nf90mpi_delete
diff --git a/src/libf90/nf90_constants.f90 b/src/libf90/nf90_constants.f90
index 93306b2..67faaa6 100644
--- a/src/libf90/nf90_constants.f90
+++ b/src/libf90/nf90_constants.f90
@@ -2,7 +2,7 @@
 !  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: nf90_constants.f90 2319 2016-02-04 08:04:01Z wkliao $
+! $Id: nf90_constants.f90 2604 2016-11-09 16:10:48Z wkliao $
 !
 ! This file is taken from netcdf_constants.f90 with changes for PnetCDF use
 !
@@ -257,8 +257,7 @@
       NF90_EQUOTA                   = NF_EQUOTA                   , & ! Quota exceeded
       NF90_ENULLSTART               = NF_ENULLSTART               , & ! argument start is a NULL pointer
       NF90_ENULLCOUNT               = NF_ENULLCOUNT               , & ! argument count is a NULL pointer
-      NF90_EINVAL_CMODE             = NF_EINVAL_CMODE             , & ! Invalid file create mode, cannot have both
-                                                                      ! NC_64BIT_OFFSET & NC_64BIT_DATA
+      NF90_EINVAL_CMODE             = NF_EINVAL_CMODE             , & ! Invalid file create mode
       NF90_ETYPESIZE                = NF_ETYPESIZE                , & ! MPI derived data type size error (bigger than the
                                                                       ! variable size)
       NF90_ETYPE_MISMATCH           = NF_ETYPE_MISMATCH           , & ! element type of the MPI derived data type mismatches
@@ -267,8 +266,10 @@
       NF90_ESTRICTCDF2              = NF_ESTRICTCDF2              , & ! Attempting CDF-5 operation on CDF-2 file
       NF90_ENOTRECVAR               = NF_ENOTRECVAR               , & ! Attempting operation only for record variables
       NF90_ENOTFILL                 = NF_ENOTFILL                 , & ! Attempting to fill a variable when its fill mode is off
+      NF90_EINVAL_OMODE             = NF_EINVAL_OMODE             , & ! Invalid file open mode
+      NF90_EPENDING                 = NF_EPENDING                 , & ! Pending nonblocking request is found at file close
       NF90_EMULTIDEFINE             = NF_EMULTIDEFINE             , & ! NC definitions on multiprocesses conflict
-      NF90_EMULTIDEFINE_OMODE       = NF_EMULTIDEFINE_OMODE       , & ! file create/open modes are inconsistent among processes
+      NF90_EMULTIDEFINE_OMODE       = NF_EMULTIDEFINE_OMODE       , & ! inconsistent file open modes
       NF90_EMULTIDEFINE_DIM_NUM     = NF_EMULTIDEFINE_DIM_NUM     , & ! inconsistent number of dimensions
       NF90_EMULTIDEFINE_DIM_SIZE    = NF_EMULTIDEFINE_DIM_SIZE    , & ! inconsistent size of dimension
       NF90_EMULTIDEFINE_DIM_NAME    = NF_EMULTIDEFINE_DIM_NAME    , & ! inconsistent dimension names
@@ -301,4 +302,5 @@
       NF90_EVARS_TYPE_MULTIDEFINE   = NF_EMULTIDEFINE_VAR_TYPE    , &
       NF90_EVARS_LEN_MULTIDEFINE    = NF_EMULTIDEFINE_VAR_LEN     , &
       NF90_ENUMRECS_MULTIDEFINE     = NF_EMULTIDEFINE_NUMRECS     , &
-      NF90_EVARS_BEGIN_MULTIDEFINE  = NF_EMULTIDEFINE_VAR_BEGIN
+      NF90_EVARS_BEGIN_MULTIDEFINE  = NF_EMULTIDEFINE_VAR_BEGIN   , &
+      NF90_EMULTIDEFINE_CMODE       = NF_EMULTIDEFINE_CMODE           ! inconsistent file create modes
diff --git a/src/libf90/nfmpi_constants.f90.in b/src/libf90/nfmpi_constants.f90.in
index d72fa0f..da03ec1 100644
--- a/src/libf90/nfmpi_constants.f90.in
+++ b/src/libf90/nfmpi_constants.f90.in
@@ -2,7 +2,7 @@
 !  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: nfmpi_constants.f90.in 2319 2016-02-04 08:04:01Z wkliao $
+! $Id: nfmpi_constants.f90.in 2614 2016-11-12 19:50:02Z wkliao $
 !
 ! This file lists the Fortran constants used by PnetCDF
 !
@@ -20,6 +20,19 @@
       parameter (PNETCDF_VERSION_SUB   = @PNETCDF_VERSION_SUB@)
 
 !
+! list of PnetCDF options enabled/disabled at configure time
+!
+      integer PNETCDF_ERANGE_FILL
+      integer PNETCDF_SUBFILING
+      integer PNETCDF_RELAX_COORD_BOUND
+      integer PNETCDF_DEBUG_MODE
+
+      parameter (PNETCDF_ERANGE_FILL       = @ENABLE_ERANGE_FILL@)
+      parameter (PNETCDF_SUBFILING         = @ENABLE_SUBFILING@)
+      parameter (PNETCDF_RELAX_COORD_BOUND = @RELAX_COORD_BOUND@)
+      parameter (PNETCDF_DEBUG_MODE        = @PNETCDF_DEBUG@)
+
+!
 ! external netcdf data types:
 !
       integer, parameter, public :: &
@@ -237,18 +250,20 @@
       NF_EQUOTA                   = -225, & ! Quota exceeded
       NF_ENULLSTART               = -226, & ! argument start is a NULL pointer
       NF_ENULLCOUNT               = -227, & ! argument count is a NULL pointer
-      NF_EINVAL_CMODE             = -228, & ! Invalid file create mode, cannot have both NC_64BIT_OFFSET & NC_64BIT_DATA
+      NF_EINVAL_CMODE             = -228, & ! Invalid file create mode
       NF_ETYPESIZE                = -229, & ! MPI derived data type size error (bigger than the variable size)
       NF_ETYPE_MISMATCH           = -230, & ! element type of the MPI derived data type mismatches the variable type
       NF_ETYPESIZE_MISMATCH       = -231, & ! file type size mismatches buffer type size
       NF_ESTRICTCDF2              = -232, & ! Attempting CDF-5 operation on CDF-2 file
       NF_ENOTRECVAR               = -233, & ! Attempting operation only for record variables */
-      NF_ENOTFILL                 = -234    ! Attempting to fill a variable when its fill mode is off */
+      NF_ENOTFILL                 = -234, & ! Attempting to fill a variable when its fill mode is off */
+      NF_EINVAL_OMODE             = -235, & ! Invalid file open mode
+      NF_EPENDING                 = -236    ! Pending nonblocking request is found at file close
 
 ! header inconsistency error starts in -250
       integer, parameter, public :: &
       NF_EMULTIDEFINE             = -250, & ! NC definitions on multiprocesses conflict
-      NF_EMULTIDEFINE_OMODE       = -251, & ! file create/open modes are inconsistent among processes
+      NF_EMULTIDEFINE_OMODE       = -251, & ! inconsistent file open modes
       NF_EMULTIDEFINE_DIM_NUM     = -252, & ! inconsistent number of dimensions
       NF_EMULTIDEFINE_DIM_SIZE    = -253, & ! inconsistent size of dimension
       NF_EMULTIDEFINE_DIM_NAME    = -254, & ! inconsistent dimension names
@@ -270,6 +285,7 @@
       NF_EMULTIDEFINE_FILL_MODE      = -270, & !  inconsistent dataset fill mode
       NF_EMULTIDEFINE_VAR_FILL_MODE  = -271, & ! inconsistent variable fill mode
       NF_EMULTIDEFINE_VAR_FILL_VALUE = -272, & ! inconsistent variable fill value
+      NF_EMULTIDEFINE_CMODE       = -273, & ! inconsistent file create modes
       NF_ECMODE                   = NF_EMULTIDEFINE_OMODE,      &
       NF_EDIMS_NELEMS_MULTIDEFINE = NF_EMULTIDEFINE_DIM_NUM,    &
       NF_EDIMS_SIZE_MULTIDEFINE   = NF_EMULTIDEFINE_DIM_SIZE,   &
diff --git a/src/libf90/visibility.f90 b/src/libf90/visibility.f90
index 96362da..de632f6 100644
--- a/src/libf90/visibility.f90
+++ b/src/libf90/visibility.f90
@@ -2,14 +2,14 @@
 !  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: visibility.f90 2013 2015-02-18 17:14:26Z wkliao $
+! $Id: visibility.f90 2584 2016-10-27 18:53:05Z wkliao $
 !
 ! This file is taken from netcdf_visibility.f90 with changes for PnetCDF use
 !
 !
 
   ! Library version, error string
-  public :: nf90mpi_inq_libvers, nf90mpi_strerror
+  public :: nf90mpi_inq_libvers, nf90mpi_strerror, nf90mpi_strerrno
   
   ! Control routines 
   public :: nf90mpi_create,   nf90mpi_open, &
diff --git a/src/utils/ncmpidiff/ncmpidiff.c b/src/utils/ncmpidiff/ncmpidiff.c
index 0ae97f3..9aec145 100644
--- a/src/utils/ncmpidiff/ncmpidiff.c
+++ b/src/utils/ncmpidiff/ncmpidiff.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2010, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: ncmpidiff.c 2150 2015-10-10 05:52:57Z wkliao $ */
+/* $Id: ncmpidiff.c 2382 2016-03-30 21:34:51Z wkliao $ */
 
 /* wkliao: This diff utility compares header and variables of two files
  *         regardless the define order of the variables and attributes.
@@ -51,13 +51,13 @@
     exit(1); \
 }
 
-#define HANDLE_ERROR {                                         \
-    if (err != NC_NOERR) {                                     \
-        fprintf(stderr, "Error at line %d (%s)\n", __LINE__,   \
-               ncmpi_strerror(err));                           \
-        MPI_Abort(MPI_COMM_WORLD, -1);                         \
-        exit(-1);                                              \
-    }                                                          \
+#define HANDLE_ERROR {                                                    \
+    if (err != NC_NOERR) {                                                \
+        fprintf(stderr, "Error at line %d of file %s (%s)\n", __LINE__,   \
+               __FILE__, ncmpi_strerror(err));                            \
+        MPI_Abort(MPI_COMM_WORLD, -1);                                    \
+        exit(-1);                                                         \
+    }                                                                     \
 }
 
 #define CHECK_GLOBAL_ATT_DIFF(type, func, nctype) {                    \
@@ -712,16 +712,16 @@ int main(int argc, char **argv)
  
         /* compare the variable contents */
         switch (type1) {
-            case NC_CHAR:   CHECK_VAR_DIFF(char,   ncmpi_get_vara_text_all,   NC_CHAR)
-            case NC_SHORT:  CHECK_VAR_DIFF(short,  ncmpi_get_vara_short_all,  NC_SHORT)
-            case NC_INT:    CHECK_VAR_DIFF(int,    ncmpi_get_vara_int_all,    NC_INT)
-            case NC_FLOAT:  CHECK_VAR_DIFF(float,  ncmpi_get_vara_float_all,  NC_FLOAT)
-            case NC_DOUBLE: CHECK_VAR_DIFF(double, ncmpi_get_vara_double_all, NC_DOUBLE)
-            case NC_UBYTE:  CHECK_VAR_DIFF(ubyte,  ncmpi_get_vara_uchar,      NC_UBYTE)
-            case NC_USHORT: CHECK_VAR_DIFF(ushort, ncmpi_get_vara_ushort,     NC_USHORT)
-            case NC_UINT:   CHECK_VAR_DIFF(uint,   ncmpi_get_vara_uint,       NC_UINT)
-            case NC_INT64:  CHECK_VAR_DIFF(int64,  ncmpi_get_vara_longlong,   NC_INT64)
-            case NC_UINT64: CHECK_VAR_DIFF(uint64, ncmpi_get_vara_ulonglong,  NC_UINT64)
+            case NC_CHAR:   CHECK_VAR_DIFF(char,   ncmpi_get_vara_text_all,      NC_CHAR)
+            case NC_SHORT:  CHECK_VAR_DIFF(short,  ncmpi_get_vara_short_all,     NC_SHORT)
+            case NC_INT:    CHECK_VAR_DIFF(int,    ncmpi_get_vara_int_all,       NC_INT)
+            case NC_FLOAT:  CHECK_VAR_DIFF(float,  ncmpi_get_vara_float_all,     NC_FLOAT)
+            case NC_DOUBLE: CHECK_VAR_DIFF(double, ncmpi_get_vara_double_all,    NC_DOUBLE)
+            case NC_UBYTE:  CHECK_VAR_DIFF(ubyte,  ncmpi_get_vara_uchar_all,     NC_UBYTE)
+            case NC_USHORT: CHECK_VAR_DIFF(ushort, ncmpi_get_vara_ushort_all,    NC_USHORT)
+            case NC_UINT:   CHECK_VAR_DIFF(uint,   ncmpi_get_vara_uint_all,      NC_UINT)
+            case NC_INT64:  CHECK_VAR_DIFF(int64,  ncmpi_get_vara_longlong_all,  NC_INT64)
+            case NC_UINT64: CHECK_VAR_DIFF(uint64, ncmpi_get_vara_ulonglong_all, NC_UINT64)
             default: ; /* TODO: handle unexpected types */
         }
     }
diff --git a/src/utils/ncmpidump/ncmpidump.c b/src/utils/ncmpidump/ncmpidump.c
index cf4695d..86ec499 100644
--- a/src/utils/ncmpidump/ncmpidump.c
+++ b/src/utils/ncmpidump/ncmpidump.c
@@ -3,7 +3,7 @@
  *   See netcdf/README file for copying and redistribution conditions.
  *   $Header$
  *********************************************************************/
-/* $Id: ncmpidump.c 2322 2016-02-26 22:47:06Z wkliao $ */
+/* $Id: ncmpidump.c 2567 2016-10-20 23:18:58Z wkliao $ */
 
 #if HAVE_CONFIG_H
 # include <ncconfig.h>
@@ -13,8 +13,9 @@
 #include <stdlib.h>  /* strtol() */
 #include <string.h>  /* strrchr() */
 #include <ctype.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <fcntl.h>   /* open() */
+#include <unistd.h>  /* read(), close() */
+#include <errno.h>   /* errno */
 
 #include <mpi.h>
 #include <pnetcdf.h>
@@ -655,6 +656,50 @@ set_precision(const char *optarg)
     set_formats(flt_digits, dbl_digits);
 }
 
+enum FILE_KIND {
+    CDF5,
+    CDF2,
+    CDF1,
+    HDF5,
+    UNKNOWN
+};
+
+static
+enum FILE_KIND check_file_signature(char *path)
+{
+    char *cdf_signature="CDF";
+    char *hdf5_signature="\211HDF\r\n\032\n";
+    char signature[8];
+    int fd, rlen;
+
+    if ((fd = open(path, O_RDONLY, 0700)) == -1) {
+        fprintf(stderr,"%s error at opening file %s (%s)\n",progname,path,strerror(errno));
+        return UNKNOWN;
+    }
+    /* get first 8 bytes of file */
+    rlen = read(fd, signature, 8);
+    if (rlen != 8) {
+        if (rlen < 0)
+            fprintf(stderr,"%s error at reading file %s (%s)\n",progname,path,strerror(errno));
+        else
+            fprintf(stderr,"%s error: unknown file format\n",progname);
+        close(fd); /* ignore error */
+        return UNKNOWN;
+    }
+    if (close(fd) == -1) {
+        fprintf(stderr,"%s error at closing file %s (%s)\n",progname,path,strerror(errno));
+        return UNKNOWN;
+    }
+    if (memcmp(signature, hdf5_signature, 8) == 0)
+        return HDF5;
+    else if (memcmp(signature, cdf_signature, 3) == 0) {
+             if (signature[3] == 5)  return CDF5;
+        else if (signature[3] == 2)  return CDF2;
+        else if (signature[3] == 1)  return CDF1;
+    }
+
+    return UNKNOWN; /* unknown format */
+}
 
 int
 main(int argc, char *argv[])
@@ -675,12 +720,14 @@ main(int argc, char *argv[])
       0,            /* if -v specified, number of variables */
       0             /* if -v specified, list of variable names */
     };
-    int c, rank, err=EXIT_SUCCESS;
+    int c, rank, nprocs, err=EXIT_SUCCESS;
     int max_len = 80;        /* default maximum line length */
     int nameopt = 0;
+    enum FILE_KIND file_kind;
 
     MPI_Init(&argc, &argv);
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
 
     /* If the user called ncmpidump without arguments, print the usage
      * message and return peacefully. */
@@ -785,22 +832,43 @@ main(int argc, char *argv[])
     if (argc != 1) {
         if (rank == 0) {
             if (argc == 0)
-                fprintf(stderr,"Error: input filename is missing\n\n");
+                fprintf(stderr,"%s error: input filename is missing\n\n",progname);
             else
-                fprintf(stderr,"Error: only one input file is allowed\n\n");
+                fprintf(stderr,"%s error: only one input file is allowed\n\n",progname);
             usage();
         }
         err = EXIT_FAILURE;
         goto fn_exit;
     }
 
+    file_kind = check_file_signature(argv[0]);
+    MPI_Bcast(&file_kind, 1, MPI_INT, 0, MPI_COMM_WORLD);
+
+    if (file_kind == UNKNOWN) {
+        err = EXIT_FAILURE;
+        goto fn_exit; /* file I/O error */
+    }
+
+    if (fspec.kind) { /* if -k option used in command line */
+             if (file_kind == CDF5) Printf ("64-bit data\n");
+        else if (file_kind == CDF2) Printf ("64-bit offset\n");
+        else if (file_kind == CDF1) Printf ("classic\n");
+        else if (file_kind == HDF5) Printf ("NetCDF-4\n");
+        goto fn_exit;
+    }
+    else if (file_kind == HDF5) {
+        if (rank == 0) fprintf(stderr,"%s error: file %s is an HDF5 file. Please use ncdump instead.\n",progname,argv[0]);
+        err = EXIT_FAILURE;
+        goto fn_exit; /* exit if is HDF5 */
+    }
+
     if (!nameopt) fspec.name = (char *)0;
     do_ncdump(argv[0], &fspec);
 #else
     /* support multiple input files */
     if (argc < 1) {
         if (rank == 0) {
-            fprintf(stderr,"Error: input filename(s) is missing\n\n");
+            fprintf(stderr,"%s error: input filename(s) is missing\n\n",progname);
             usage();
         }
         err = EXIT_FAILURE;
@@ -808,6 +876,27 @@ main(int argc, char *argv[])
     }
     int i = 0;
     do {
+        if (rank == 0)
+            file_kind = check_hdf5_signature(argv[i]);
+        MPI_Bcast(&file_kind, 1, MPI_INT, 0, MPI_COMM_WORLD);
+
+        if (file_kind == UNKNOWN) {
+            err = EXIT_FAILURE;
+            goto fn_exit; /* file I/O error */
+        }
+        if (fspec.kind) { /* if -k option used in command line */
+                 if (file_kind == CDF5) Printf ("64-bit data\n");
+            else if (file_kind == CDF2) Printf ("64-bit offset\n");
+            else if (file_kind == CDF1) Printf ("classic\n");
+            else if (file_kind == HDF5) Printf ("NetCDF-4\n");
+            goto fn_exit;
+        }
+        else if (file_kind == HDF5) {
+            if (rank == 0) fprintf(stderr,"%s error: file %s is an HDF5 file. Please use ncdump instead.\n",progname,argv[i]);
+            err = EXIT_FAILURE;
+            goto fn_exit; /* exit if is HDF5 */
+        }
+
         if (!nameopt) fspec.name = (char *)0;
         if (argc > 0)
               do_ncdump(argv[i], &fspec);
diff --git a/src/utils/ncmpigen/genlib.c b/src/utils/ncmpigen/genlib.c
index b159c64..4357879 100644
--- a/src/utils/ncmpigen/genlib.c
+++ b/src/utils/ncmpigen/genlib.c
@@ -107,7 +107,7 @@ gen_netcdf(
 				    (double *) atts[iatt].val);
 	    break;
 	case NC_UBYTE:
-	    stat = ncmpi_put_att_ubyte(ncid, varid, atts[iatt].name,
+	    stat = ncmpi_put_att_uchar(ncid, varid, atts[iatt].name,
 				    atts[iatt].type, atts[iatt].len,
 				    (unsigned char *) atts[iatt].val);
 	    break;
diff --git a/src/utils/ncmpigen/main.c b/src/utils/ncmpigen/main.c
index 00e96d8..eb148e8 100644
--- a/src/utils/ncmpigen/main.c
+++ b/src/utils/ncmpigen/main.c
@@ -183,6 +183,7 @@ main(int argc, char *argv[])
 					  "64-bit-variables") == 0) {
 			  giantvar_flag = 1;
 		  }
+                  free(version_name);
 	  }
 	  break;
 	case '?':
diff --git a/src/utils/ncmpivalid/ncmpivalid.c b/src/utils/ncmpivalid/ncmpivalid.c
index 59a9831..af0d39e 100644
--- a/src/utils/ncmpivalid/ncmpivalid.c
+++ b/src/utils/ncmpivalid/ncmpivalid.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: ncmpivalid.c 2335 2016-03-03 14:55:12Z wkliao $ */
+/* $Id: ncmpivalid.c 2569 2016-10-22 17:12:17Z wkliao $ */
 
 #if HAVE_CONFIG_H
 # include <ncconfig.h>
@@ -44,9 +44,6 @@ static int val_get_NC_var(bufferinfo *gbp, NC_var **varpp);
 static int val_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap);
 static int val_get_NC(NC *ncp);
 
-static int val_fetch(bufferinfo *gbp, MPI_Offset fsize);
-static int val_check_buffer(bufferinfo *gbp, MPI_Offset nextread);
-
 
 #define ABORT {printf("Abort: at line=%d func=%s\n", __LINE__,__func__); fflush(stdout); MPI_Abort(MPI_COMM_WORLD, -1);}
 
@@ -56,7 +53,7 @@ static int val_check_buffer(bufferinfo *gbp, MPI_Offset nextread);
  * Fetch the next header chunk.
  */
 static int
-val_fetch(bufferinfo *gbp, MPI_Offset fsize) {
+val_fetch(bufferinfo *gbp) {
   ssize_t nn = 0;
   MPI_Offset slack;        /* any leftover data in the buffer */
   MPI_Aint pos_addr, base_addr;
@@ -71,8 +68,8 @@ val_fetch(bufferinfo *gbp, MPI_Offset fsize) {
     MPI_Address(gbp->base, &base_addr);
 #endif
   slack = gbp->size - (pos_addr - base_addr);
-  /* . if gbp->pos and gbp->base are the same, there is no leftover buffer data
-   *   to worry about.  
+  /* if gbp->pos and gbp->base are the same, there is no leftover buffer data
+   * to worry about.  
    * In the other extreme, where gbp->size == (gbp->pos - gbp->base), then all
    * data in the buffer has been consumed */
   if (slack == gbp->size) slack = 0;
@@ -114,7 +111,7 @@ val_check_buffer(bufferinfo *gbp,
     if (pos_addr + nextread <= base_addr + gbp->size)
         return NC_NOERR;
 
-    return val_fetch(gbp, MIN(gbp->size, nextread));
+    return val_fetch(gbp);
 } 
 
 static int
@@ -193,7 +190,7 @@ val_get_NC_string(bufferinfo *gbp, NC_string **ncstrpp) {
       cpos += strcount; 
       bufremain -= strcount;
     } else {
-      status = val_fetch(gbp, MIN(gbp->size, X_SIZEOF_CHAR * nchars));
+      status = val_fetch(gbp);
       if(status != NC_NOERR) {
 	printf("fetching the name string of ");
         ncmpii_free_NC_string(ncstrp);
@@ -374,7 +371,7 @@ val_get_NC_attrV(bufferinfo *gbp, NC_attr *attrp) {
       value = (void *)((char *)value + attcount);
       bufremain -= attcount;
     } else {
-      status = val_fetch(gbp, MIN(gbp->size, esz * nvalues));
+      status = val_fetch(gbp);
       if(status != NC_NOERR) {
 	printf("fetching the values of ");
         return status;
@@ -659,7 +656,7 @@ static int
 val_get_NC(NC *ncp) {
     int status;
     bufferinfo getbuf;
-    schar magic[sizeof(ncmagic)];
+    char magic[sizeof(ncmagic)];
     MPI_Offset nrecs = 0;
     MPI_Aint pos_addr, base_addr;
 
@@ -668,8 +665,6 @@ val_get_NC(NC *ncp) {
     /* Initialize the get buffer that stores the header read from the file */
     getbuf.nciop = ncp->nciop;
     getbuf.offset = 0;     /* read from start of the file */
-    getbuf.put_size = 0;   /* amount of writes so far in bytes */
-    getbuf.get_size = 0;   /* amount of reads  so far in bytes */
 
     /* CDF-5's minimum header size is 4 bytes more than CDF-1 and CDF-2's */
     getbuf.size = _RNDUP( MAX(MIN_NC_XSZ+4, ncp->chunk), X_ALIGN );
@@ -680,7 +675,7 @@ val_get_NC(NC *ncp) {
     getbuf.index = 0;
 
     /* Fetch the next header chunk. The chunk is 'gbp->size' bytes big */
-    status = val_fetch(&getbuf, sizeof(magic));
+    status = val_fetch(&getbuf);
     if (status != NC_NOERR) {
         printf("magic number (C D F \\001) is expected!\n");
         return status;
@@ -688,8 +683,8 @@ val_get_NC(NC *ncp) {
   
     /* First get the file format information, magic */
     memset(magic, 0, sizeof(magic));
-    status = ncmpix_getn_schar_schar((const void **)(&getbuf.pos),
-                                     sizeof(magic), magic);
+    status = ncmpix_getn_text((const void **)(&getbuf.pos), sizeof(magic),
+                              magic);
     getbuf.index += sizeof(magic);
 
     if (memcmp(magic, ncmagic, sizeof(ncmagic)-1) != 0) {
@@ -843,7 +838,13 @@ int main(int argc, char **argv) {
     }
 
     /* check data size */
-    fstat(ncp->nciop->fd, &ncfilestat);
+    if (-1 == fstat(ncp->nciop->fd, &ncfilestat)) {
+        printf("Error at line %d fstat (%s)\n",__LINE__,strerror(errno));
+        close(ncp->nciop->fd);
+        ncmpiio_free(ncp->nciop);
+        ncmpii_free_NC(ncp);
+        return 0;
+    }
     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);
diff --git a/src/utils/ncoffsets/ncoffsets.c b/src/utils/ncoffsets/ncoffsets.c
index 3c56294..87ea0ef 100644
--- a/src/utils/ncoffsets/ncoffsets.c
+++ b/src/utils/ncoffsets/ncoffsets.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: ncoffsets.c 2335 2016-03-03 14:55:12Z wkliao $ */
+/* $Id: ncoffsets.c 2444 2016-05-22 23:48:35Z wkliao $ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -13,9 +13,9 @@
 #include <fcntl.h>     /* open() */
 #include <unistd.h>    /* read() */
 #include <assert.h>    /* assert() */
-#include <inttypes.h>  /* check for Endianness */
+#include <inttypes.h>  /* check for Endianness, uint32_t*/
 
-static int endianness;
+static int is_little_endian;
 
 #ifndef MIN
 #define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
@@ -200,54 +200,56 @@ static const char ncmagic5[] = {'C', 'D', 'F', 0x05};
 
 const char * ncmpii_err_code_name(int err);
 
-static int is_little_endian(void) {
+static int check_little_endian(void) {
     volatile uint32_t i=0x01234567;
     // return 0 for big endian, 1 for little endian.
     return (*((uint8_t*)(&i))) == 0x67;
 }
 
+#define SWAP4B(a) ( ((a) << 24) | \
+                   (((a) <<  8) & 0x00ff0000) | \
+                   (((a) >>  8) & 0x0000ff00) | \
+                   (((a) >> 24) & 0x000000ff) )
+
+#define SWAP8B(a) ( (((a) & 0x00000000000000FFULL) << 56) | \
+                    (((a) & 0x000000000000FF00ULL) << 40) | \
+                    (((a) & 0x0000000000FF0000ULL) << 24) | \
+                    (((a) & 0x00000000FF000000ULL) <<  8) | \
+                    (((a) & 0x000000FF00000000ULL) >>  8) | \
+                    (((a) & 0x0000FF0000000000ULL) >> 24) | \
+                    (((a) & 0x00FF000000000000ULL) >> 40) | \
+                    (((a) & 0xFF00000000000000ULL) >> 56) )
+
 static void
-swap4b(int *val)
+swap4b(void *val)
 {
-    unsigned int tmp = *val;
-    char *ip = (char*) &tmp;
-    char *op = (char*) val;
-    op[0] = ip[3];
-    op[1] = ip[2];
-    op[2] = ip[1];
-    op[3] = ip[0];
+    uint32_t *op = (uint32_t*)val;
+    *op = SWAP4B(*op);
 }
 
 static void
 swap8b(long long *val)
 {
-    unsigned long long tmp = *val;
-    char *ip = (char*) &tmp;
-    char *op = (char*) val;
-    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];
+    uint64_t *op = (uint64_t*)val;
+    *op = SWAP8B(*op);
 }
 
 static unsigned long long
-get_uint8(bufferinfo *gbp) {
+get_uint64(bufferinfo *gbp) {
+    /* retrieve a 64bit unisgned integer and return it as unsigned long long */
     unsigned long long tmp;
     memcpy(&tmp, gbp->pos, 8);
-    if (endianness) swap8b(&tmp);
+    if (is_little_endian) swap8b(&tmp);
     gbp->pos += 8;
     return tmp;
 }
 
 static unsigned int
-get_uint4(bufferinfo *gbp) {
+get_uint32(bufferinfo *gbp) {
+    /* retrieve a 32bit unisgned integer and return it as unsigned int */
     unsigned int tmp;
     memcpy(&tmp, gbp->pos, 4);
-    if (endianness) swap4b(&tmp);
+    if (is_little_endian) swap4b(&tmp);
     gbp->pos += 4;
     return tmp;
 }
@@ -824,7 +826,7 @@ hdr_get_NCtype(bufferinfo *gbp,
     if (status != NC_NOERR) return status;
 
     /* get a 4-byte integer */
-    *typep = get_uint4(gbp);
+    *typep = get_uint32(gbp);
 
     return NC_NOERR;
 }
@@ -840,7 +842,7 @@ hdr_get_nc_type(bufferinfo *gbp,
     status = hdr_check_buffer(gbp, X_SIZEOF_INT);
     if (status != NC_NOERR) return status;
 
-    type = get_uint4(gbp);
+    type = get_uint32(gbp);
 
     if (type != NC_BYTE    &&
         type != NC_CHAR    &&
@@ -883,9 +885,9 @@ hdr_get_NC_name(bufferinfo  *gbp,
 
     /* get nelems */
     if (gbp->version == 5) 
-        nchars = get_uint8(gbp);
+        nchars = get_uint64(gbp);
     else
-        nchars = get_uint4(gbp);
+        nchars = get_uint32(gbp);
 
     /* Allocate a NC_string structure large enough to hold nchars characters */
     ncstrp = ncmpii_new_NC_string(nchars, NULL);
@@ -967,9 +969,9 @@ hdr_get_NC_dim(bufferinfo  *gbp,
 
     /* get dim_length */
     if (gbp->version == 5) 
-        dimp->size = get_uint8(gbp);
+        dimp->size = get_uint64(gbp);
     else
-        dimp->size = get_uint4(gbp);
+        dimp->size = get_uint32(gbp);
 
     *dimpp = dimp;
     return NC_NOERR;
@@ -1029,9 +1031,9 @@ hdr_get_NC_dimarray(bufferinfo  *gbp,
 
     /* get nelems */
     if (gbp->version == 5) 
-        ndefined = get_uint8(gbp);
+        ndefined = get_uint64(gbp);
     else
-        ndefined = get_uint4(gbp);
+        ndefined = get_uint32(gbp);
     ncap->ndefined = (int)ndefined;
 
     if (ndefined == 0) {
@@ -1202,9 +1204,9 @@ hdr_get_NC_attr(bufferinfo  *gbp,
 
     /* get nelems */
     if (gbp->version == 5) 
-        nelems = get_uint8(gbp);
+        nelems = get_uint64(gbp);
     else
-        nelems = get_uint4(gbp);
+        nelems = get_uint32(gbp);
 
     /* allocate space for attribute object */
     attrp = ncmpii_new_x_NC_attr(strp, type, nelems);
@@ -1267,9 +1269,9 @@ hdr_get_NC_attrarray(bufferinfo   *gbp,
 
     /* get nelems */
     if (gbp->version == 5) 
-        ndefined = get_uint8(gbp);
+        ndefined = get_uint64(gbp);
     else
-        ndefined = get_uint4(gbp);
+        ndefined = get_uint32(gbp);
     ncap->ndefined = (int)ndefined;
 
     if (ndefined == 0) {
@@ -1369,9 +1371,9 @@ hdr_get_NC_var(bufferinfo  *gbp,
 
     /* nelems */
     if (gbp->version == 5) 
-        ndims = get_uint8(gbp);
+        ndims = get_uint64(gbp);
     else
-        ndims = get_uint4(gbp);
+        ndims = get_uint32(gbp);
 
     /* allocate space for var object */
     varp = ncmpii_new_x_NC_var(strp, (int)ndims);
@@ -1384,9 +1386,9 @@ hdr_get_NC_var(bufferinfo  *gbp,
             return status;
         }
         if (gbp->version == 5) 
-            varp->dimids[dim] = get_uint8(gbp);
+            varp->dimids[dim] = get_uint64(gbp);
         else
-            varp->dimids[dim] = get_uint4(gbp);
+            varp->dimids[dim] = get_uint32(gbp);
     }
 
     /* get vatt_list */
@@ -1405,9 +1407,9 @@ hdr_get_NC_var(bufferinfo  *gbp,
 
     /* get vsize */
     if (gbp->version == 5) 
-        varp->len = get_uint8(gbp);
+        varp->len = get_uint64(gbp);
     else
-        varp->len = get_uint4(gbp);
+        varp->len = get_uint32(gbp);
 
     /* next element is 'begin' */
     status = hdr_check_buffer(gbp, (gbp->version == 1 ? 4 : 8));
@@ -1418,9 +1420,9 @@ hdr_get_NC_var(bufferinfo  *gbp,
 
     /* get begin */
     if (gbp->version == 1)
-        varp->begin = get_uint4(gbp);
+        varp->begin = get_uint32(gbp);
     else
-        varp->begin = get_uint8(gbp);
+        varp->begin = get_uint64(gbp);
 
     *varpp = varp;
     return NC_NOERR;
@@ -1479,9 +1481,9 @@ hdr_get_NC_vararray(bufferinfo  *gbp,
 
     /* get nelems (number of variables) from gbp buffer */
     if (gbp->version == 5) 
-        ndefined = get_uint8(gbp);
+        ndefined = get_uint64(gbp);
     else
-        ndefined = get_uint4(gbp);
+        ndefined = get_uint32(gbp);
     ncap->ndefined = (int)ndefined;
 
     if (ndefined == 0) { /* no variable defined */
@@ -1577,9 +1579,9 @@ ncmpii_hdr_get_NC(int fd, NC *ncp)
 
     /* get numrecs from getbuf into ncp */
     if (getbuf.version == 5) 
-        ncp->numrecs = get_uint8(&getbuf);
+        ncp->numrecs = get_uint64(&getbuf);
     else
-        ncp->numrecs = get_uint4(&getbuf);
+        ncp->numrecs = get_uint32(&getbuf);
 
     /* get dim_list from getbuf into ncp */
     status = hdr_get_NC_dimarray(&getbuf, &ncp->dims);
@@ -1818,7 +1820,7 @@ int main(int argc, char *argv[])
     if (env_str != NULL && *env_str != '0') verbose_debug = 1;
 
     /* find Endianness of the running machine */
-    endianness = is_little_endian();
+    is_little_endian = check_little_endian();
 
     /* open file */
     int fd = open(filename, O_RDONLY, 0666);
diff --git a/src/utils/pnetcdf_version/Makefile.in b/src/utils/pnetcdf_version/Makefile.in
index 1d6e216..4be7286 100644
--- a/src/utils/pnetcdf_version/Makefile.in
+++ b/src/utils/pnetcdf_version/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2014, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2264 2015-12-22 15:42:59Z wkliao $
+# $Id: Makefile.in 2478 2016-09-08 21:31:52Z wkliao $
 #
 # @configure_input@
 
diff --git a/test/C/Makefile.in b/test/C/Makefile.in
index 3501c82..0f57c5b 100644
--- a/test/C/Makefile.in
+++ b/test/C/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2259 2015-12-22 04:51:01Z wkliao $
+# $Id: Makefile.in 2590 2016-10-31 21:37:02Z wkliao $
 #
 # @configure_input@
 
@@ -14,9 +14,6 @@ include ../../macros.make
 INCLUDES  = -I../../src/lib -I$(srcdir)/../common
 LDFLAGS  := $(LDFLAGS) -L../common
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
-ifeq (@PNC_DEBUG@, yes)
-CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
-endif
 
 SRCS    = pres_temp_4D_wr.c \
           pres_temp_4D_rd.c
@@ -53,6 +50,7 @@ check testing verbose_testing: $(PROGS)
 
 TEST_MPIRUN_2  = $(subst NP,2,$(TEST_MPIRUN))
 TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_6  = $(subst NP,6,$(TEST_MPIRUN))
 
 ptest2: $(PROGS)
 	@for i in $(PROGS); do ( \
@@ -64,11 +62,16 @@ ptest4: $(PROGS)
 	$(TEST_MPIRUN_4) ./$$i $(TEST_OUTDIR)/testfile.nc \
 	; ) ; done
 
+ptest6: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_6) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
 ptest: ptest4
 
-ptests: ptest2 ptest4
+ptests: ptest2 ptest4 ptest6
 
-ptest6 ptest8 ptest10:
+ptest8 ptest10:
 
 include $(srcdir)/../../rules.make
 
diff --git a/test/C/pres_temp_4D_rd.c b/test/C/pres_temp_4D_rd.c
index 315417f..8dad3a6 100644
--- a/test/C/pres_temp_4D_rd.c
+++ b/test/C/pres_temp_4D_rd.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: pres_temp_4D_rd.c 2133 2015-09-26 19:16:01Z wkliao $ */
+/* $Id: pres_temp_4D_rd.c 2491 2016-09-25 03:36:28Z wkliao $ */
 
 /*
    This is an example which reads some 4D pressure and
@@ -16,10 +16,11 @@
    Full documentation of the netCDF C API can be found at:
    http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c
 
-   $Id: pres_temp_4D_rd.c 2133 2015-09-26 19:16:01Z wkliao $
+   $Id: pres_temp_4D_rd.c 2491 2016-09-25 03:36:28Z wkliao $
 */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <pnetcdf.h>
 #include <mpi.h>
@@ -66,7 +67,7 @@
 #define CHECK_ERR { \
     if (err != NC_NOERR) { \
         nerrs++; \
-        printf("Error: %s a5 line %d (%s)\n", __FILE__,__LINE__,ncmpi_strerror(err)); } }
+        printf("Error: %s at line %d (%s)\n", __FILE__,__LINE__,ncmpi_strerror(err)); } }
 
 
 int
@@ -81,8 +82,8 @@ main(int argc, char **argv)
 
    /* Program variables to hold the data we will read. We will only
       need enough space to hold one timestep of data; one record. */
-   float pres_in[NLVL][NLAT][NLON];
-   float temp_in[NLVL][NLAT][NLON];
+   float **pres_in; /* [NLVL/nprocs][NLAT][NLON] */
+   float **temp_in; /* [NLVL/nprocs][NLAT][NLON] */
 
    /* These program variables hold the latitudes and longitudes. */
    float lats[NLAT], lons[NLON];
@@ -148,34 +149,54 @@ main(int argc, char **argv)
     * that the data arrays in this program are the correct size to
     * hold one timestep. */
    count[0] = 1;
-   count[1] = NLVL/nprocs;
    count[2] = NLAT;
    count[3] = NLON;
-   start[1] = 0;
    start[2] = 0;
    start[3] = 0;
+ 
+   /* divide NLVL dimension among processes */
+   count[1] = NLVL / nprocs;
+   start[1] = count[1] * rank;
+   if (rank < NLVL % nprocs) {
+       start[1] += rank;
+       count[1]++;
+   }
+   else {
+       start[1] += NLVL % nprocs;
+   }
+   if (count[1] == 0) start[1] = 0;
+
+   /* allocate read buffers */
+   pres_in = (float**) malloc(count[1]*2 * sizeof(float*));
+   temp_in = pres_in + count[1];
+   if (count[1] > 0) {
+       pres_in[0] = (float*) malloc(count[1]*2 * NLAT*NLON * sizeof(float));
+       temp_in[0] = pres_in[0] + count[1] * NLAT*NLON;
+       for (i=1; i<count[1]; i++) {
+           pres_in[i] = pres_in[i-1] + NLAT*NLON;
+           temp_in[i] = temp_in[i-1] + NLAT*NLON;
+       }
+   }
 
    /* Read and check one record at a time. */
    for (rec = 0; rec < NREC; rec++)
    {
       start[0] = rec;
-      err = ncmpi_get_vara_float_all(ncid, pres_varid, start, 
-				      count, &pres_in[0][0][0]);
+      err = ncmpi_get_vara_float_all(ncid, pres_varid, start, count, &pres_in[0][0]);
       CHECK_ERR
-      err = ncmpi_get_vara_float_all(ncid, temp_varid, start,
-				      count, &temp_in[0][0][0]);
+      err = ncmpi_get_vara_float_all(ncid, temp_varid, start, count, &temp_in[0][0]);
       CHECK_ERR
 
       /* Check the data. */
-      i = 0;
-      for (lvl = 0; lvl < NLVL/nprocs; lvl++)
+      i = (int)start[1] * NLAT * NLON;
+      for (lvl=0; lvl<count[1]; lvl++)
 	 for (lat = 0; lat < NLAT; lat++)
 	    for (lon = 0; lon < NLON; lon++)
 	    {
-	       if (pres_in[lvl][lat][lon] != SAMPLE_PRESSURE + i) 
-		  return 2;
-	       if (temp_in[lvl][lat][lon] != SAMPLE_TEMP + i) 
-		  return 2;
+	       if (pres_in[lvl][lat*NLON+lon] != SAMPLE_PRESSURE + i) 
+		  nerrs++;
+	       if (temp_in[lvl][lat*NLON+lon] != SAMPLE_TEMP + i) 
+		  nerrs++;
 	       i++;
 	    }
 
@@ -185,6 +206,9 @@ main(int argc, char **argv)
    err = ncmpi_close(ncid);
    CHECK_ERR
 
+   if (count[1] > 0) free(pres_in[0]);
+   free(pres_in);
+
     /* check if there is any malloc residue */
     MPI_Offset malloc_size, sum_size;
     err = ncmpi_inq_malloc_size(&malloc_size);
@@ -195,6 +219,7 @@ main(int argc, char **argv)
                    sum_size);
     }
 
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
     if (rank == 0) {
         if (nerrs) printf(FAIL_STR,nerrs);
         else       printf(PASS_STR);
diff --git a/test/C/pres_temp_4D_wr.c b/test/C/pres_temp_4D_wr.c
index 325692a..2037606 100644
--- a/test/C/pres_temp_4D_wr.c
+++ b/test/C/pres_temp_4D_wr.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: pres_temp_4D_wr.c 2133 2015-09-26 19:16:01Z wkliao $ */
+/* $Id: pres_temp_4D_wr.c 2392 2016-04-04 23:15:04Z wkliao $ */
 
 
 /*
@@ -17,10 +17,11 @@
    Full documentation of the netCDF C API can be found at:
    http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c
 
-   $Id: pres_temp_4D_wr.c 2133 2015-09-26 19:16:01Z wkliao $
+   $Id: pres_temp_4D_wr.c 2392 2016-04-04 23:15:04Z wkliao $
 */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <pnetcdf.h>
 #include <mpi.h>
@@ -90,8 +91,8 @@ main(int argc, char ** argv)
 
    /* Program variables to hold the data we will write out. We will only
       need enough space to hold one timestep of data; one record. */
-   float pres_out[NLVL][NLAT][NLON];
-   float temp_out[NLVL][NLAT][NLON];
+   float **pres_out; /* [NLVL/nprocs][NLAT][NLON] */
+   float **temp_out; /* [NLVL/nprocs][NLAT][NLON] */
 
    /* These program variables hold the latitudes and longitudes. */
    float lats[NLAT], lons[NLON];
@@ -128,14 +129,6 @@ main(int argc, char ** argv)
       lats[lat] = START_LAT + 5.*lat;
    for (lon = 0; lon < NLON; lon++)
       lons[lon] = START_LON + 5.*lon;
-   
-   for (lvl = 0; lvl < NLVL; lvl++)
-      for (lat = 0; lat < NLAT; lat++)
-	 for (lon = 0; lon < NLON; lon++)
-	 {
-	    pres_out[lvl][lat][lon] = SAMPLE_PRESSURE + i;
-	    temp_out[lvl][lat][lon] = SAMPLE_TEMP + i++;
-	 }
 
    /* Create the file. */
    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, MPI_INFO_NULL, &ncid);
@@ -204,10 +197,12 @@ main(int argc, char ** argv)
    err = ncmpi_begin_indep_data(ncid);
    /* Write the coordinate variable data. This will put the latitudes
       and longitudes of our data grid into the netCDF file. */
-   err = ncmpi_put_var_float(ncid, lat_varid, &lats[0]);
-   CHECK_ERR
-   err = ncmpi_put_var_float(ncid, lon_varid, &lons[0]);
-   CHECK_ERR
+   if (rank == 0) {
+       err = ncmpi_put_var_float(ncid, lat_varid, &lats[0]);
+       CHECK_ERR
+       err = ncmpi_put_var_float(ncid, lon_varid, &lons[0]);
+       CHECK_ERR
+   }
    err = ncmpi_end_indep_data(ncid);
    CHECK_ERR
 
@@ -216,13 +211,44 @@ main(int argc, char ** argv)
                     &data[0][0][0]);
      timestep to write.) */
    count[0] = 1;
-   count[1] = NLVL/nprocs;
    count[2] = NLAT;
    count[3] = NLON;
-   start[1] = 0;
    start[2] = 0;
    start[3] = 0;
 
+   /* divide NLVL dimension among processes */
+   count[1] = NLVL / nprocs;
+   start[1] = count[1] * rank;
+   if (rank < NLVL % nprocs) {
+       start[1] += rank;
+       count[1]++;
+   }
+   else {
+       start[1] += NLVL % nprocs;
+   }
+   if (count[1] == 0) start[1] = 0;
+
+   /* allocate write buffers */
+   pres_out = (float**) malloc(count[1]*2 * sizeof(float*));
+   temp_out = pres_out + count[1];
+   if (count[1] > 0) {
+       pres_out[0] = (float*) malloc(count[1]*2 * NLAT*NLON * sizeof(float));
+       temp_out[0] = pres_out[0] + count[1] * NLAT*NLON;
+       for (i=1; i<count[1]; i++) {
+           pres_out[i] = pres_out[i-1] + NLAT*NLON;
+           temp_out[i] = temp_out[i-1] + NLAT*NLON;
+       }
+   }
+
+   /* initialize write buffers */
+   i = (int)start[1] * NLAT * NLON;
+   for (lvl=0; lvl<count[1]; lvl++)
+      for (lat = 0; lat < NLAT; lat++)
+	 for (lon = 0; lon < NLON; lon++) {
+	    pres_out[lvl][lat*NLON + lon] = SAMPLE_PRESSURE + i;
+	    temp_out[lvl][lat*NLON + lon] = SAMPLE_TEMP + i++;
+	 }
+
    /* Write the pretend data. This will write our surface pressure and
       surface temperature data. The arrays only hold one timestep worth
       of data. We will just rewrite the same data for each timestep. In
@@ -231,9 +257,9 @@ main(int argc, char ** argv)
    for (rec = 0; rec < NREC; rec++)
    {
       start[0] = rec;
-      err = ncmpi_put_vara_float_all(ncid, pres_varid, start, count, &pres_out[0][0][0]);
+      err = ncmpi_put_vara_float_all(ncid, pres_varid, start, count, &pres_out[0][0]);
       CHECK_ERR
-      err = ncmpi_put_vara_float_all(ncid, temp_varid, start, count, &temp_out[0][0][0]);
+      err = ncmpi_put_vara_float_all(ncid, temp_varid, start, count, &temp_out[0][0]);
       CHECK_ERR
    }
 
@@ -241,6 +267,9 @@ main(int argc, char ** argv)
    err = ncmpi_close(ncid);
    CHECK_ERR
    
+   if (count[1] > 0) free(pres_out[0]);
+   free(pres_out);
+
     /* check if there is any malloc residue */
     MPI_Offset malloc_size, sum_size;
     err = ncmpi_inq_malloc_size(&malloc_size);
@@ -251,6 +280,7 @@ main(int argc, char ** argv)
                    sum_size);
     }
 
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
     if (rank == 0) {
         if (nerrs) printf(FAIL_STR,nerrs);
         else       printf(PASS_STR);
diff --git a/test/CXX/Makefile.in b/test/CXX/Makefile.in
index beadd0e..0034d3a 100644
--- a/test/CXX/Makefile.in
+++ b/test/CXX/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2014, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+# $Id: Makefile.in 2590 2016-10-31 21:37:02Z wkliao $
 #
 # @configure_input@
 
@@ -14,9 +14,6 @@ include ../../macros.make
 INCLUDES  = -I../../src/lib -I../../src/libcxx -I$(srcdir)/../common
 LDFLAGS  := $(LDFLAGS) -L../common
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
-ifeq (@PNC_DEBUG@, yes)
-CXXCPPFLAGS := $(CXXCPPFLAGS) -DPNC_DEBUG
-endif
 
 SRCS    = nctst.cpp \
           test_classic.cpp
diff --git a/test/F90/f90tst_parallel.f90 b/test/F90/f90tst_parallel.f90
index bf838bd..b0939a6 100644
--- a/test/F90/f90tst_parallel.f90
+++ b/test/F90/f90tst_parallel.f90
@@ -4,7 +4,7 @@
 !
 !     This is part of the PnetCDF package.
 !
-!     $Id: f90tst_parallel.f90 2131 2015-09-25 22:33:12Z wkliao $
+!     $Id: f90tst_parallel.f90 2512 2016-09-29 01:29:37Z wkliao $
 
 !     This program tests PnetCDF parallel I/O functions from fortran 90.
 !
@@ -147,8 +147,10 @@ program f90tst_parallel
   ! Close the file.
   call handle_err(nf90mpi_close(ncid))
 
-  msg = '*** TESTING F90 '//trim(cmd)
-  if (my_rank .eq. 0) call pass_fail(0, msg)
+  if (my_rank .eq. 0) then
+     msg = '*** TESTING F90 '//trim(cmd)
+     call pass_fail(0, msg)
+  endif
 
  999 call MPI_Finalize(ierr)
 
diff --git a/test/F90/f90tst_parallel2.f90 b/test/F90/f90tst_parallel2.f90
index 1662a43..c51baf3 100644
--- a/test/F90/f90tst_parallel2.f90
+++ b/test/F90/f90tst_parallel2.f90
@@ -4,7 +4,7 @@
 !
 !     This is part of the PnetCDF package.
 !
-!     $Id: f90tst_parallel2.f90 2131 2015-09-25 22:33:12Z wkliao $
+!     $Id: f90tst_parallel2.f90 2512 2016-09-29 01:29:37Z wkliao $
 
 !     This program tests PnetCDF parallel I/O functions from fortran 90.
 
@@ -41,7 +41,7 @@
 !   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ ;
 ! }
 
-!     $Id: f90tst_parallel2.f90 2131 2015-09-25 22:33:12Z wkliao $
+!     $Id: f90tst_parallel2.f90 2512 2016-09-29 01:29:37Z wkliao $
 
 program f90tst_parallel
   use mpi
@@ -155,8 +155,10 @@ program f90tst_parallel
   ! Close the file. 
   call handle_err(nf90mpi_close(ncid))
 
-  msg = '*** TESTING F90 '//trim(cmd)//' for strided access'
-  if (my_rank .eq. 0) call pass_fail(0, msg)
+  if (my_rank .eq. 0) then
+      msg = '*** TESTING F90 '//trim(cmd)//' for strided access'
+      call pass_fail(0, msg)
+  endif
 
  999 call MPI_Finalize(ierr)
 
diff --git a/test/F90/f90tst_parallel3.f90 b/test/F90/f90tst_parallel3.f90
index efaa595..8d622a6 100644
--- a/test/F90/f90tst_parallel3.f90
+++ b/test/F90/f90tst_parallel3.f90
@@ -4,7 +4,7 @@
 !
 !     This is part of the PnetCDF package.
 !
-!     $Id: f90tst_parallel3.f90 2136 2015-10-07 19:25:34Z wkliao $
+!     $Id: f90tst_parallel3.f90 2512 2016-09-29 01:29:37Z wkliao $
 
 !     This program tests PnetCDF parallel I/O from
 !     fortran. It creates a file like this:
@@ -175,8 +175,10 @@ program f90tst_parallel3
   ! Close the file. 
   call check(nf90mpi_close(ncid))
 
-   msg = '*** TESTING F90 '//trim(cmd)
-   if (my_rank .eq. 0) call pass_fail(0, msg)
+   if (my_rank .eq. 0) then
+       msg = '*** TESTING F90 '//trim(cmd)
+       call pass_fail(0, msg)
+   endif
 
  999 call MPI_Finalize(ierr)
 
diff --git a/test/F90/f90tst_parallel4.f90 b/test/F90/f90tst_parallel4.f90
index 8c6a889..70986e4 100644
--- a/test/F90/f90tst_parallel4.f90
+++ b/test/F90/f90tst_parallel4.f90
@@ -4,7 +4,7 @@
 !
 !     This is part of the PnetCDF package.
 !
-! $Id: f90tst_parallel4.f90 2136 2015-10-07 19:25:34Z wkliao $
+! $Id: f90tst_parallel4.f90 2512 2016-09-29 01:29:37Z wkliao $
 
 ! This parallel test was contributed by Jim Edwards at UCAR. Thanks Jim!
 program f90tst
@@ -83,8 +83,10 @@ program f90tst
 
   call handle_err(nf90mpi_close(fh))
 
-  msg = '*** TESTING F90 '//trim(cmd)
-  if (my_rank .eq. 0) call pass_fail(0, msg)
+  if (my_rank .eq. 0) then
+      msg = '*** TESTING F90 '//trim(cmd)
+      call pass_fail(0, msg)
+  endif
 
  999 call MPI_Finalize(ierr)
 
diff --git a/test/cdf_format/Makefile.in b/test/cdf_format/Makefile.in
index 2bdd397..4e1300f 100644
--- a/test/cdf_format/Makefile.in
+++ b/test/cdf_format/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2306 2016-01-12 19:34:31Z wkliao $
+# $Id: Makefile.in 2590 2016-10-31 21:37:02Z wkliao $
 #
 # @configure_input@
 
@@ -14,9 +14,6 @@ include ../../macros.make
 INCLUDES  = -I../../src/lib -I$(srcdir)/../common
 LDFLAGS  := $(LDFLAGS) -L../common
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
-ifeq (@PNC_DEBUG@, yes)
-CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
-endif
 
 SRCS    = test_inq_format.c \
           cdf_type.c \
diff --git a/test/common/Makefile.in b/test/common/Makefile.in
index fb4f214..59911e1 100644
--- a/test/common/Makefile.in
+++ b/test/common/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2219 2015-12-11 22:30:03Z wkliao $
+# $Id: Makefile.in 2590 2016-10-31 21:37:02Z wkliao $
 #
 # @configure_input@
 
@@ -13,11 +13,6 @@ include ../../macros.make
 
 INCLUDES  = -I../../src/lib
 
-ifeq (@PNC_DEBUG@, yes)
-CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
-FPPFLAGS := $(FPPFLAGS) @FC_DEFINE at PNC_DEBUG
-endif
-
 C_SRCS   = testutils.c
 
 F_SRCS   = testutilsf.F90
diff --git a/test/common/testutils.c b/test/common/testutils.c
index c49e03c..456d814 100644
--- a/test/common/testutils.c
+++ b/test/common/testutils.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: testutils.c 2247 2015-12-20 20:29:06Z wkliao $ */
+/* $Id: testutils.c 2563 2016-10-18 02:43:48Z wkliao $ */
 
 
 #include <stdio.h>
@@ -59,6 +59,16 @@ void parse_write_args(int argc, char **argv, int rank, params *p)
 char* nc_err_code_name(int err)
 {
     static char unknown_str[32];
+
+    if (err > 0) { /* system error */
+        const char *cp = (const char *) strerror(err);
+        if (cp == NULL)
+            sprintf(unknown_str,"Unknown error code %d",err);
+        else
+            sprintf(unknown_str,"Error code %d (%s)",err,cp);
+        return unknown_str;
+    }
+
     switch (err) {
         case (NC_NOERR):			return "NC_NOERR";
         case (NC_EBADID):			return "NC_EBADID";
@@ -170,6 +180,7 @@ char* nc_err_code_name(int err)
         case (NC_ENULLSTART):			return "NC_ENULLSTART";
         case (NC_ENULLCOUNT):			return "NC_ENULLCOUNT";
         case (NC_EINVAL_CMODE):			return "NC_EINVAL_CMODE";
+        case (NC_EINVAL_OMODE):			return "NC_EINVAL_OMODE";
         case (NC_ETYPESIZE):			return "NC_ETYPESIZE";
         case (NC_ETYPE_MISMATCH):		return "NC_ETYPE_MISMATCH";
         case (NC_ETYPESIZE_MISMATCH):		return "NC_ETYPESIZE_MISMATCH";
@@ -178,6 +189,7 @@ char* nc_err_code_name(int err)
         case (NC_ENOTFILL):			return "NC_ENOTFILL";
         case (NC_EMULTIDEFINE):			return "NC_EMULTIDEFINE";
         case (NC_EMULTIDEFINE_OMODE):		return "NC_EMULTIDEFINE_OMODE";
+        case (NC_EMULTIDEFINE_CMODE):		return "NC_EMULTIDEFINE_CMODE";
         case (NC_EMULTIDEFINE_DIM_NUM):		return "NC_EMULTIDEFINE_DIM_NUM";
         case (NC_EMULTIDEFINE_DIM_SIZE):	return "NC_EMULTIDEFINE_DIM_SIZE";
         case (NC_EMULTIDEFINE_DIM_NAME):	return "NC_EMULTIDEFINE_DIM_NAME";
diff --git a/test/common/testutils.h b/test/common/testutils.h
index ef2b7a4..80a04ce 100644
--- a/test/common/testutils.h
+++ b/test/common/testutils.h
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: testutils.h 2133 2015-09-26 19:16:01Z wkliao $ */
+/* $Id: testutils.h 2590 2016-10-31 21:37:02Z wkliao $ */
 
 
 #ifndef _UTILS_H
@@ -22,7 +22,7 @@ typedef struct {
 void parse_read_args(int argc, char **argv, int rank, params *p);
 void parse_write_args(int argc, char **argv, int rank, params *p);
 
-#ifdef PNC_DEBUG
+#ifdef PNETCDF_DEBUG
 #define PASS_STR "\x1b[32mpass\x1b[0m\n"
 #define FAIL_STR "\x1b[31mfail\x1b[0m with %d mismatches\n"
 #else
@@ -32,4 +32,8 @@ void parse_write_args(int argc, char **argv, int rank, params *p);
 
 extern char* nc_err_code_name(int err);
 
+#ifndef MPI_OFFSET
+#define MPI_OFFSET MPI_LONG_LONG_INT
+#endif
+
 #endif
diff --git a/test/common/testutilsf.F90 b/test/common/testutilsf.F90
index cfc7657..dc4a786 100644
--- a/test/common/testutilsf.F90
+++ b/test/common/testutilsf.F90
@@ -4,7 +4,7 @@
 !
 !     This is part of the PnetCDF package.
 !
-!     $Id: testutilsf.F90 2133 2015-09-26 19:16:01Z wkliao $
+!     $Id: testutilsf.F90 2590 2016-10-31 21:37:02Z wkliao $
 
       ! This function gets the executable name and output file name from the
       ! command line.
@@ -40,7 +40,7 @@
           CHARACTER ESC
           PARAMETER (ESC=char(27))
 
-#ifdef PNC_DEBUG
+#ifdef PNETCDF_DEBUG
           CHARACTER (LEN=20) PASS_STR, FAIL_STR
           PARAMETER (PASS_STR='------ '//ESC//'[32mpass'//ESC//'[0m')
           PARAMETER (FAIL_STR='------ '//ESC//'[31mfail'//ESC//'[0m')
diff --git a/test/fandc/Makefile.in b/test/fandc/Makefile.in
index e91e3a3..99fe701 100644
--- a/test/fandc/Makefile.in
+++ b/test/fandc/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+# $Id: Makefile.in 2590 2016-10-31 21:37:02Z wkliao $
 #
 # @configure_input@
 
@@ -16,9 +16,6 @@ INCLUDES  = -I../../src/lib -I$(srcdir)/../common
 FPPFLAGS += -I../../src/libf @FC_MODINC at ../../src/libf90
 LDFLAGS  := $(LDFLAGS) -L../common
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
-ifeq (@PNC_DEBUG@, yes)
-CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
-endif
 
 C_SRCS   = pnctest.c \
            csnap.c
diff --git a/test/header/Makefile.in b/test/header/Makefile.in
index 9dd45fa..7a5329f 100644
--- a/test/header/Makefile.in
+++ b/test/header/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+# $Id: Makefile.in 2590 2016-10-31 21:37:02Z wkliao $
 #
 # @configure_input@
 
@@ -14,9 +14,6 @@ include ../../macros.make
 INCLUDES  = -I../../src/lib -I$(srcdir)/../common
 LDFLAGS  := $(LDFLAGS) -L../common
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
-ifeq (@PNC_DEBUG@, yes)
-CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
-endif
 
 SRCS      = header_consistency.c
 
diff --git a/test/header/header_consistency.c b/test/header/header_consistency.c
index 235adf2..5e947ee 100644
--- a/test/header/header_consistency.c
+++ b/test/header/header_consistency.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: header_consistency.c 2200 2015-11-28 17:54:14Z wkliao $ */
+/* $Id: header_consistency.c 2497 2016-09-26 06:48:05Z wkliao $ */
 
 /* This program tests if PnetCDF can detect file header inconsistency and
  * overwrite the inconsistent header with root's.
@@ -17,7 +17,7 @@
 #include <testutils.h>
 
 #define ERR_EXP(e, exp) {if (e != exp) { printf("Error (line %d): expecting error code %s but got %s\n", __LINE__, nc_err_code_name(exp), nc_err_code_name(e)); nerrs++; }}
-#define ERR_EXP2(e, exp1, exp2) {if (e != exp1 && e != exp2) { printf("Error (line %d): expecting error code %s or %s but got %s\n", __LINE__, nc_err_code_name(exp1), nc_err_code_name(exp2), nc_err_code_name(e)); nerrs++; }}
+#define ERR_EXP2(e, exp1, exp2) {if (e != exp1 && e != exp2 && e != NC_EFILE) { printf("Error (line %d): expecting error code %s or %s but got %s\n", __LINE__, nc_err_code_name(exp1), nc_err_code_name(exp2), nc_err_code_name(e)); nerrs++; }}
 
 #define CHECK_ERR(expect) { \
     if (safe_mode) { \
@@ -50,58 +50,24 @@ int test_open_mode(char *filename, int safe_mode)
     cmode = NC_CLOBBER|NC_64BIT_OFFSET;
     if (rank == 0) cmode = NC_CLOBBER;
     err = ncmpi_create(comm, filename, cmode, info, &ncid);
-    /* if safe_mode is on, then we expect all non-root ranks to print a warning
-     * message "inconsistent file create mode, overwrite with root's" and error
-     * code NC_EMULTIDEFINE_OMODE from non-root processes.
-     * if safe_mode is off, then no error code should be returned.
-     */
-    if (safe_mode && rank > 0) ERR_EXP(err, NC_EMULTIDEFINE_OMODE)
-    else                       ERR
-
-    err = ncmpi_close(ncid);
-    /* if safe_mode is on, then no error code should be returned.
-     * if safe_mode is off, then we expect error code NC_EMULTIDEFINE_OMODE
-     * from all non-root processes and NC_EMULTIDEFINE from root process.
-     */
-    if (safe_mode) ERR
-    else if (rank > 0) ERR_EXP(err, NC_EMULTIDEFINE_OMODE)
-
-    int format;
-    err = ncmpi_inq_file_format(filename, &format); ERR
-    if (format != 1) {
-        printf("Error (line %d): output file should be in CDF-1 format\n",__LINE__);
-        nerrs++;
+    if (safe_mode)
+        ERR_EXP(err, NC_EMULTIDEFINE_CMODE)
+    else {
+        if (rank > 0) ERR_EXP(err, NC_EMULTIDEFINE_CMODE)
+        err = ncmpi_close(ncid); ERR
     }
 
     /* Test inconsistent omode -----------------------------------------------*/
     omode = NC_WRITE;
     if (rank == 0) omode = NC_NOWRITE;
     err = ncmpi_open(comm, filename, omode, info, &ncid);
-    if (safe_mode) {
-        /* in safe_mode, we expect all non-root ranks to print a warning message
-         * "inconsistent file open mode, overwrite with root's" and error code
-         * code NC_EMULTIDEFINE_OMODE and no error on root process.
-         */
-        if (rank == 0) ERR
-        else           ERR_EXP(err, NC_EMULTIDEFINE_OMODE)
-
-        /* in safe mode, open mode inconsistent is not a fatal error, file is
-         * still opened, with root's omode overwriting others. Hence, once the
-         * test is done, we need to close the file */
-        err = ncmpi_close(ncid); ERR
-    }
+    if (safe_mode)
+        ERR_EXP(err, NC_EMULTIDEFINE_OMODE)
     else {
-        /* expected errors: NC_EMULTIDEFINE_OMODE or NC_EMULTIDEFINE_FNC_ARGS */
-        ERR_EXP2(err, NC_EMULTIDEFINE_OMODE, NC_EMULTIDEFINE_FNC_ARGS)
-
-        /* When not in safe mode, the inconsistent omode will be passed to
-         * MPI_File_open(). MPI-IO should return error class MPI_ERR_NOT_SAME
-         * which will be translated to NC_EMULTIDEFINE_FNC_ARGS in PnetCDF.
-         * If MPI-IO reports error class MPI_ERR_AMODE instead, then it will be
-         * translated to NC_EMULTIDEFINE_OMODE in PnetCDF. In any case, the file
-         * will not be opened by MPI-IO and hence we need not close the file.
-         */
+        if (rank > 0) ERR_EXP(err, NC_EMULTIDEFINE_OMODE)
+        err = ncmpi_close(ncid); ERR
     }
+
     return nerrs;
 }
 
@@ -109,76 +75,34 @@ int test_open_mode(char *filename, int safe_mode)
 static
 int test_dim(char *filename, int safe_mode)
 {
-    int err, rank, ncid, cmode, ndims, dimid1, dimid2, dimid3, nerrs=0;
-    MPI_Offset dimlen;
+    int err, rank, ncid, cmode, dimid1, dimid2, dimid3, nerrs=0;
     MPI_Info info=MPI_INFO_NULL;
     MPI_Comm comm=MPI_COMM_WORLD;
 
     MPI_Comm_rank(comm, &rank);
     cmode = NC_CLOBBER|NC_64BIT_OFFSET;
 
-    /* Test inconsistency on number of dimensions ----------------------------*/
-    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
-    err = ncmpi_def_dim(ncid, "x", 100, &dimid1); ERR
-    if (rank == 0) {
-        err = ncmpi_def_dim(ncid, "y", 100, &dimid2); ERR
-    }
-    err = ncmpi_enddef(ncid);
-    /* expected errors: NC_EMULTIDEFINE or NC_EMULTIDEFINE_DIM_NUM */
-    CHECK_ERR(NC_EMULTIDEFINE_DIM_NUM)
-
-    err = ncmpi_inq_ndims(ncid, &ndims); ERR
-    if (ndims != 2) {
-        printf("Error (line %d): number of dimesnions (%d) defined should be 2\n",__LINE__,ndims);
-        nerrs++;
-    }
-    /* all processes should be able to see dim "y" */
-    err = ncmpi_inq_dimid(ncid, "y", &dimid2);
-    if (err != NC_NOERR) {
-        printf("Error (line %d): all processes should be able to see dim \"y\"\n",__LINE__);
-        nerrs++;
-        ERR
-    }
-    err = ncmpi_close(ncid); ERR
-
-    /* Test inconsistency on number of dimensions ----------------------------*/
-    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
-    err = ncmpi_def_dim(ncid, "x", 100, &dimid1); ERR
-    if (rank > 0) {
-        err = ncmpi_def_dim(ncid, "y", 100, &dimid2); ERR
-    }
-    err = ncmpi_enddef(ncid);
-    /* expected errors: NC_EMULTIDEFINE or NC_EMULTIDEFINE_DIM_NUM */
-    CHECK_ERR(NC_EMULTIDEFINE_DIM_NUM)
-
-    err = ncmpi_inq_ndims(ncid, &ndims); ERR
-    if (ndims != 1) {
-        printf("Error (line %d): number of dimesnions (%d) defined should be 1\n",__LINE__,ndims);
-        nerrs++;
-    }
-    /* no process should be able to get dim "y" */
-    err = ncmpi_inq_dimid(ncid, "y", &dimid2);
-    CHECK_ERR(NC_EBADDIM)
-
-    err = ncmpi_close(ncid); ERR
-
     /* Test inconsistency on dimension names ---------------------------------*/
     err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
     if (rank == 0)
         err = ncmpi_def_dim(ncid, "y", 100, &dimid1);
     else
         err = ncmpi_def_dim(ncid, "xx", 100, &dimid1);
-    ERR
-    err = ncmpi_enddef(ncid);
-    /* expected errors: NC_EMULTIDEFINE or NC_EMULTIDEFINE_DIM_NAME */
-    CHECK_ERR(NC_EMULTIDEFINE_DIM_NAME)
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_DIM_NAME)
+    else
+        ERR
+    err = ncmpi_enddef(ncid); ERR
 
-    /* all processes should be able to get dim "y" */
-    err = ncmpi_inq_dimid(ncid, "y", &dimid2); ERR
+    if (safe_mode) {
+        /* no processes should be able to see dim "y" */
+        err = ncmpi_inq_dimid(ncid, "y", &dimid2);
+        CHECK_ERR(NC_EBADDIM)
 
-    /* no process should be able to get dim "x" */
-    err = ncmpi_inq_dimid(ncid, "xx", &dimid3);
-    CHECK_ERR(NC_EBADDIM)
+        /* no process should be able to see dim "x" */
+        err = ncmpi_inq_dimid(ncid, "xx", &dimid3);
+        CHECK_ERR(NC_EBADDIM)
+    }
 
     err = ncmpi_close(ncid); ERR
 
@@ -188,17 +112,10 @@ int test_dim(char *filename, int safe_mode)
         err = ncmpi_def_dim(ncid, "x", 99, &dimid1);
     else
         err = ncmpi_def_dim(ncid, "x", 100, &dimid1);
-    ERR
-    err = ncmpi_enddef(ncid);
-    /* expected errors: NC_EMULTIDEFINE or NC_EMULTIDEFINE_DIM_SIZE */
-    CHECK_ERR(NC_EMULTIDEFINE_DIM_SIZE)
-
-    /* all processes should be able to get dim "x" of size == 99 */
-    err = ncmpi_inq_dimlen(ncid, dimid1, &dimlen); ERR
-    if (dimlen != 99) {
-        printf("Error (line %d): dimesnion size (%lld) should be 99\n",__LINE__,dimlen);
-        nerrs++;
-    }
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_DIM_SIZE)
+    else
+        ERR
 
     err = ncmpi_close(ncid); ERR
     return nerrs;
@@ -218,27 +135,15 @@ int test_attr(char *filename, int safe_mode)
     MPI_Comm_rank(comm, &rank);
     cmode = NC_CLOBBER|NC_64BIT_OFFSET;
 
-    /* Test inconsistent global attribute numbers ----------------------------*/
-    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
-    int_attr = 1;
-    flt_attr = 1.0;
-    err = ncmpi_put_att_int(ncid, NC_GLOBAL, "gattr_1", NC_INT, 1, &int_attr);
-    ERR
-    if (rank == 0) {
-        err = ncmpi_put_att_float(ncid, NC_GLOBAL, "gattr_2", NC_FLOAT, 1,
-                                  &flt_attr); ERR
-    }
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_ATTR_NUM)
-    err = ncmpi_close(ncid); ERR
-
     /* Test inconsistent global attribute name -------------------------------*/
     err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
     int_attr = 1;
     sprintf(gattr, "gattr_name.%d",rank);
-    err = ncmpi_put_att_int(ncid, NC_GLOBAL, gattr, NC_INT, 1, &int_attr); ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_ATTR_NAME)
+    err = ncmpi_put_att_int(ncid, NC_GLOBAL, gattr, NC_INT, 1, &int_attr);
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_ATTR_NAME)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent global attribute type -------------------------------*/
@@ -247,9 +152,10 @@ int test_attr(char *filename, int safe_mode)
         err = ncmpi_put_att_int(ncid, NC_GLOBAL, "gatt", NC_INT, 1, &int_attr);
     else
         err = ncmpi_put_att_float(ncid, NC_GLOBAL, "gatt", NC_FLOAT, 1, &flt_attr);
-    ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_ATTR_TYPE)
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_ATTR_TYPE)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent global attribute length -----------------------------*/
@@ -259,18 +165,20 @@ int test_attr(char *filename, int safe_mode)
         err = ncmpi_put_att_int(ncid, NC_GLOBAL, "gatt", NC_INT, 2, intv);
     else
         err = ncmpi_put_att_int(ncid, NC_GLOBAL, "gatt", NC_INT, 1, intv);
-    ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_ATTR_LEN)
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_ATTR_LEN)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent global attribute length -----------------------------*/
     err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
     if (rank == 0) intv[1]=3;
     err = ncmpi_put_att_int(ncid, NC_GLOBAL, "gatt", NC_INT, 2, intv);
-    ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_ATTR_VAL)
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_ATTR_VAL)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     return nerrs;
@@ -281,42 +189,26 @@ static
 int test_var(char *filename, int safe_mode)
 {
     int err, rank, ncid, cmode, nerrs=0;
-    int ndims, dimid[3], nvars, varid1, varid2, int_attr;
+    int dimid[3], varid1, int_attr;
     float flt_attr;
     char name[128], var_attr[128];
-    nc_type xtype;
-    MPI_Offset dimlen;
     MPI_Info info=MPI_INFO_NULL;
     MPI_Comm comm=MPI_COMM_WORLD;
 
     MPI_Comm_rank(comm, &rank);
     cmode = NC_CLOBBER|NC_64BIT_OFFSET;
 
-    /* Test inconsistent variable attribute numbers --------------------------*/
-    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
-    err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
-    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, dimid, &varid1); ERR
-    int_attr = 1;
-    flt_attr = 1.0;
-    err = ncmpi_put_att_int(ncid, varid1, "var_attr_1", NC_INT, 1, &int_attr);
-    ERR
-    if (rank == 0) {
-        err = ncmpi_put_att_float(ncid, varid1, "var_attr_2", NC_FLOAT, 1,
-                                  &flt_attr); ERR
-    }
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_ATTR_NUM)
-    err = ncmpi_close(ncid); ERR
-
     /* Test inconsistent global attribute name -------------------------------*/
     err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
     err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
     err = ncmpi_def_var(ncid, "var1", NC_INT, 1, dimid, &varid1); ERR
     int_attr = 1;
     sprintf(var_attr, "var_attr_name.%d",rank);
-    err = ncmpi_put_att_int(ncid, varid1, var_attr, NC_INT, 1, &int_attr); ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_ATTR_NAME)
+    err = ncmpi_put_att_int(ncid, varid1, var_attr, NC_INT, 1, &int_attr);
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_ATTR_NAME)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent global attribute type -------------------------------*/
@@ -327,9 +219,10 @@ int test_var(char *filename, int safe_mode)
         err = ncmpi_put_att_int(ncid, varid1, "var_att", NC_INT, 1, &int_attr);
     else
         err = ncmpi_put_att_float(ncid, varid1, "var_att", NC_FLOAT, 1, &flt_attr);
-    ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_ATTR_TYPE)
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_ATTR_TYPE)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent global attribute length -----------------------------*/
@@ -341,9 +234,10 @@ int test_var(char *filename, int safe_mode)
         err = ncmpi_put_att_int(ncid, varid1, "var_att", NC_INT, 2, intv);
     else
         err = ncmpi_put_att_int(ncid, varid1, "var_att", NC_INT, 1, intv);
-    ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_ATTR_LEN)
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_ATTR_LEN)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent global attribute length -----------------------------*/
@@ -352,41 +246,21 @@ int test_var(char *filename, int safe_mode)
     err = ncmpi_def_var(ncid, "var1", NC_INT, 1, dimid, &varid1); ERR
     if (rank == 0) intv[1]=3;
     err = ncmpi_put_att_int(ncid, varid1, "var_att", NC_INT, 2, intv);
-    ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_ATTR_VAL)
-    err = ncmpi_close(ncid); ERR
-
-    /* Test inconsistent number of variables ---------------------------------*/
-    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
-    err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
-    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, dimid, &varid1); ERR
-    if (rank == 0) {
-        err = ncmpi_def_var(ncid, "var2", NC_INT, 1, dimid, &varid2); ERR
-    }
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_VAR_NUM)
-
-    err = ncmpi_inq_nvars(ncid, &nvars); ERR
-    if (nvars != 2) {
-        printf("Error (line %d): all processes should see 2 variables\n",__LINE__);
-        nerrs++;
-    }
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_ATTR_VAL)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent variable name ---------------------------------------*/
     err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
     err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
     sprintf(name, "var.%d",rank);
-    err = ncmpi_def_var(ncid, name, NC_INT, 1, dimid, &varid1); ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_VAR_NAME)
-
-    err = ncmpi_inq_varname(ncid, varid1, name); ERR
-    if (strcmp(name, "var.0")) {
-        printf("Error (line %d): all processes should see variable name: \"var.0\"\n",__LINE__);
-        nerrs++;
-    }
+    err = ncmpi_def_var(ncid, name, NC_INT, 1, dimid, &varid1);
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_VAR_NAME)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent variable ndims --------------------------------------*/
@@ -397,15 +271,10 @@ int test_var(char *filename, int safe_mode)
         err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid, &varid1);
     else
         err = ncmpi_def_var(ncid, "var", NC_FLOAT, 1, dimid, &varid1);
-    ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_VAR_NDIMS)
-
-    err = ncmpi_inq_varndims(ncid, varid1, &ndims); ERR
-    if (ndims != 2) {
-        printf("Error (line %d): all processes should see var has 2 dimensions\n",__LINE__);
-        nerrs++;
-    }
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_VAR_NDIMS)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent variable type ---------------------------------------*/
@@ -415,15 +284,10 @@ int test_var(char *filename, int safe_mode)
         err = ncmpi_def_var(ncid, "var", NC_INT, 1, dimid, &varid1);
     else
         err = ncmpi_def_var(ncid, "var", NC_FLOAT, 1, dimid, &varid1);
-    ERR
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_VAR_TYPE)
-
-    err = ncmpi_inq_vartype(ncid, varid1, &xtype); ERR
-    if (xtype != NC_INT) {
-        printf("Error (line %d): all processes should see var is of type NC_INT\n",__LINE__);
-        nerrs++;
-    }
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_VAR_TYPE)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent variable length -------------------------------------*/
@@ -431,36 +295,14 @@ int test_var(char *filename, int safe_mode)
     err = ncmpi_def_dim(ncid, "dim0", 5, &dimid[0]); ERR
     err = ncmpi_def_dim(ncid, "dim1", 4, &dimid[1]); ERR
     err = ncmpi_def_dim(ncid, "dim2", 3, &dimid[2]); ERR
-    if (rank == 0) {
-        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid, &varid1); ERR
-    }
-    else {
-        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid+1, &varid1); ERR
-    }
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_VAR_LEN)
-
-    err = ncmpi_inq_vardimid(ncid, varid1, dimid); ERR
-    err = ncmpi_inq_dimname(ncid, dimid[0], name); ERR
-    if (strcmp(name, "dim0")) {
-        printf("Error (line %d): all processes should see var's dim[0] name \"dim0\"\n",__LINE__);
-        nerrs++;
-    }
-    err = ncmpi_inq_dimname(ncid, dimid[1], name); ERR
-    if (strcmp(name, "dim1")) {
-        printf("Error (line %d): all processes should see var's dim[1] name \"dim1\"\n",__LINE__);
-        nerrs++;
-    }
-    err = ncmpi_inq_dimlen(ncid, dimid[0], &dimlen); ERR
-    if (dimlen != 5) {
-        printf("Error (line %d): all processes should see var's dim[0] len == 5\n",__LINE__);
-        nerrs++;
-    }
-    err = ncmpi_inq_dimlen(ncid, dimid[1], &dimlen); ERR
-    if (dimlen != 4) {
-        printf("Error (line %d): all processes should see var's dim[1] len == 4\n",__LINE__);
-        nerrs++;
-    }
+    if (rank == 0)
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid, &varid1);
+    else
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid+1, &varid1);
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_VAR_DIMIDS)
+    else
+        ERR
     err = ncmpi_close(ncid); ERR
 
     /* Test inconsistent variable dimension IDs ------------------------------*/
@@ -468,87 +310,17 @@ int test_var(char *filename, int safe_mode)
     err = ncmpi_def_dim(ncid, "Z", 3, &dimid[0]); ERR
     err = ncmpi_def_dim(ncid, "Y", 3, &dimid[1]); ERR
     err = ncmpi_def_dim(ncid, "X", 3, &dimid[2]); ERR
-    if (rank == 0) {
-        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid+1, &varid1); ERR
-    }
-    else {
-        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid, &varid1); ERR
-    }
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_VAR_DIMIDS)
-
-    err = ncmpi_inq_vardimid(ncid, varid1, dimid); ERR
-    err = ncmpi_inq_dimname(ncid, dimid[0], name); ERR
-    if (strcmp(name, "Y")) {
-        printf("Error (line %d): all processes should see var's dim[0] name \"Y\"\n",__LINE__);
-        nerrs++;
-    }
-    err = ncmpi_inq_dimname(ncid, dimid[1], name); ERR
-    if (strcmp(name, "X")) {
-        printf("Error (line %d): all processes should see var's dim[1] name \"X\"\n",__LINE__);
-        nerrs++;
-    }
-    err = ncmpi_close(ncid); ERR
-
-    return nerrs;
-}
-
-/*----< test_dim_var() >------------------------------------------------------*/
-static
-int test_dim_var(char *filename, int safe_mode)
-{
-    int i, err, rank, ncid, cmode, nerrs=0;
-    int ndims, dimid[3], varid1;
-    char name[128], dimname[128];
-    MPI_Offset dimlen;
-    MPI_Info info=MPI_INFO_NULL;
-    MPI_Comm comm=MPI_COMM_WORLD;
-
-    MPI_Comm_rank(comm, &rank);
-    cmode = NC_CLOBBER|NC_64BIT_OFFSET;
-
-    /* Test inconsistent of dimensions impact to variables -------------------*/
-    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
-    err = ncmpi_def_dim(ncid, "dim1", 5, &dimid[0]); ERR
-    err = ncmpi_def_dim(ncid, "dim2", 4, &dimid[1]); ERR
-    if (rank == 0) {
-        err = ncmpi_def_dim(ncid, "dim3", 3, &dimid[2]); ERR
-        err = ncmpi_def_var(ncid, "var1", NC_INT, 2, dimid+1, &varid1); ERR
-    }
-    else {
-        err = ncmpi_def_var(ncid, "var1", NC_INT, 2, dimid, &varid1); ERR
-    }
-    err = ncmpi_enddef(ncid);
-    CHECK_ERR(NC_EMULTIDEFINE_DIM_NUM)
+    if (rank == 0)
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid+1, &varid1);
+    else
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid, &varid1);
+    if (safe_mode)
+        CHECK_ERR(NC_EMULTIDEFINE_VAR_DIMIDS)
+    else
+        ERR
 
-    err = ncmpi_inq_ndims(ncid, &ndims); ERR
-    if (ndims != 3) {
-        printf("Error (line %d): all processes should see 3 dimensions\n",__LINE__);
-        nerrs++;
-    }
-    dimid[0] = dimid[1] = dimid[2] = -1;
-    err = ncmpi_inq_vardimid(ncid, varid1, dimid); ERR
-    for (i=0; i<2; i++) {
-        err = ncmpi_inq_dimname(ncid, dimid[i], name); ERR
-        sprintf(dimname, "dim%d", i);
-        if (!strcmp(name, dimname)) {
-            printf("Error (line %d): all processes should see dimid[%d] name \"%s\"\n",__LINE__,i,dimname);
-            nerrs++;
-        }
-    }
-    err = ncmpi_inq_dimlen(ncid, dimid[0], &dimlen); ERR
-    if (dimlen != 4) {
-        printf("Error (line %d): all processes should see dimid[0] len = 4\n",__LINE__);
-        nerrs++;
-    }
-    err = ncmpi_inq_dimlen(ncid, dimid[1], &dimlen); ERR
-    if (dimlen != 3) {
-        printf("Error (line %d): all processes should see dimid[1] len = 3\n",__LINE__);
-        nerrs++;
-    }
     err = ncmpi_close(ncid); ERR
 
-
     return nerrs;
 }
 
@@ -581,7 +353,7 @@ int main(int argc, char **argv)
         printf("%-66s ------ ", cmd_str);
     }
 
-    verbose = 0;
+    verbose = 1;
     for (i=verbose; i>=0; i--) {
         /* test with safe mode off and on :
          * Note even if --enable-debug is set at configure time, safe mode
@@ -596,8 +368,6 @@ int main(int argc, char **argv)
         nerrs += test_attr(filename, i);
 
         nerrs += test_var(filename, i);
-
-        nerrs += test_dim_var(filename, i);
     }
 
     MPI_Offset malloc_size, sum_size;
diff --git a/test/largefile/Makefile.in b/test/largefile/Makefile.in
index c931567..2b3c67b 100644
--- a/test/largefile/Makefile.in
+++ b/test/largefile/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+# $Id: Makefile.in 2590 2016-10-31 21:37:02Z wkliao $
 #
 # @configure_input@
 
@@ -14,9 +14,6 @@ include ../../macros.make
 INCLUDES  = -I../../src/lib -I$(srcdir)/../common
 LDFLAGS  := $(LDFLAGS) -L../common
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
-ifeq (@PNC_DEBUG@, yes)
-CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
-endif
 
 ifeq (@is_bigendian@, yes)
 DEFS := $(DEFS) -DWORDS_BIGENDIAN
diff --git a/test/nc_test/Makefile.in b/test/nc_test/Makefile.in
index 3940659..b01298f 100644
--- a/test/nc_test/Makefile.in
+++ b/test/nc_test/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2294 2016-01-06 20:10:13Z wkliao $
+# $Id: Makefile.in 2614 2016-11-12 19:50:02Z wkliao $
 #
 # @configure_input@
 
@@ -11,16 +11,11 @@ VPATH  = @srcdir@
 
 include ../../macros.make
 
-INCLUDES  = -I../../src/lib -I$(srcdir) -I$(srcdir)/../common
+INCLUDES  = -I. -I../../src/lib -I$(srcdir) -I$(srcdir)/../common
 LDFLAGS  := -L../common $(LDFLAGS)
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) -lm @LCOV_LIB@
-ifeq (@PNC_DEBUG@, yes)
-CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
-endif
 
-SRCS      = test_read.c \
-            test_write.c \
-            error.c \
+SRCS      = error.c \
             util.c
 
 PROG_SRCS = nc_test.c \
@@ -33,36 +28,38 @@ PROG_SRCS = nc_test.c \
             tst_atts.c \
             tst_nofill.c
 
+M4_HEADERS = tests.h.m4
+
 M4_SRCS   = test_get.m4 \
             test_put.m4 \
             test_iget.m4 \
-            test_iput.m4
+            test_iput.m4 \
+            test_read.m4 \
+            test_write.m4
 
-HEADERS   = tests.h \
-            error.h
+HEADERS   = error.h
 
 OBJS      = $(SRCS:.c=.o) $(M4_SRCS:.m4=.o)
 
 PROGS     = $(PROG_SRCS:.c=)
 
-GARBAGE      = $(PROGS) $(M4_SRCS:.m4=.c) \
-               test.nc testfile.nc scratch.nc testfile.nc.2 \
-               testfile.nc.nofill testfile.nc.fill
+GARBAGE   = $(PROGS) $(M4_SRCS:.m4=.c) tests.h \
+            test.nc testfile.nc scratch.nc testfile.nc.2 \
+            testfile.nc.nofill testfile.nc.fill
 
-PACKING_LIST = $(SRCS) $(M4_SRCS) $(HEADERS) $(PROG_SRCS) \
+PACKING_LIST = $(SRCS) $(M4_SRCS) $(M4_HEADERS) $(HEADERS) $(PROG_SRCS) \
                Makefile.in depend README
 
 all: $(PROGS)
 
-$(OBJS): $(srcdir)/../common/testutils.h
-
-$(PROG_SRCS:.c=.o): $(srcdir)/../common/testutils.h
-
 $(PROGS): ../common/libtestutils.a
 
 ../common/libtestutils.a:
 	set -e; cd ../common && $(MAKE) $(MFLAGS) all
 
+tests.h: tests.h.m4
+	$(M4) $(M4FLAGS) $< >$@
+
 nc_test: nc_test.o $(OBJS) $(LIBRARY)
 	$(LINK.c) $< $(OBJS) $(LDFLAGS) $(LIBS)
 
diff --git a/test/nc_test/depend b/test/nc_test/depend
index a29bc04..b3a4b9f 100644
--- a/test/nc_test/depend
+++ b/test/nc_test/depend
@@ -1,41 +1,33 @@
 error.o: error.c
-nc_test.o: ../../src/lib/pnetcdf.h
-nc_test.o: error.h
-nc_test.o: nc_test.c
-nc_test.o: tests.h
-test_get.o: ../../src/lib/pnetcdf.h
-test_get.o: error.h
-test_get.o: test_get.c
-test_get.o: tests.h
-test_put.o: ../../src/lib/pnetcdf.h
-test_put.o: error.h
-test_put.o: test_put.c
-test_put.o: tests.h
-test_iget.o: ../../src/lib/pnetcdf.h
-test_iget.o: error.h
-test_iget.o: test_iget.c
-test_iget.o: tests.h
-test_iput.o: ../../src/lib/pnetcdf.h
-test_iput.o: error.h
-test_iput.o: test_iput.c
-test_iput.o: tests.h
-test_read.o: ../../src/lib/pnetcdf.h
-test_read.o: error.h
-test_read.o: test_read.c
-test_read.o: tests.h
-test_write.o: ../../src/lib/pnetcdf.h
-test_write.o: error.h
-test_write.o: test_write.c
-test_write.o: tests.h
-util.o: ../../src/lib/pnetcdf.h
-util.o: error.h
-util.o: tests.h
-util.o: util.c
-t_nc.o: t_nc.c
-tst_misc.o: tst_misc.c
-tst_norm.o: tst_norm.c
-tst_small.o: tst_small.c
-tst_names.o: tst_names.c
-tst_atts3.o: tst_atts3.c
-tst_atts.o: tst_atts.c
-tst_nofill.o: tst_nofill.c
+test_read.o: test_read.c tests.h ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h error.h ../../src/lib/ncconfig.h
+test_write.o: test_write.c tests.h ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h error.h ../../src/lib/ncconfig.h
+util.o: util.c tests.h ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h error.h ../../src/lib/ncconfig.h
+test_get.o: test_get.c tests.h ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h error.h ../../src/lib/ncconfig.h
+test_put.o: test_put.c tests.h ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h error.h ../../src/lib/ncconfig.h
+test_iget.o: test_iget.c tests.h ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h error.h ../../src/lib/ncconfig.h
+test_iput.o: test_iput.c tests.h ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h error.h ../../src/lib/ncconfig.h
+nc_test.o: nc_test.c tests.h ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h error.h ../../src/lib/ncconfig.h
+t_nc.o: t_nc.c ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h
+tst_misc.o: tst_misc.c ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h
+tst_norm.o: tst_norm.c ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h
+tst_small.o: tst_small.c ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h
+tst_names.o: tst_names.c ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h
+tst_atts3.o: tst_atts3.c ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h
+tst_atts.o: tst_atts.c ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h
+tst_nofill.o: tst_nofill.c ../../src/lib/pnetcdf.h \
+  $(srcdir)/../common/testutils.h
diff --git a/test/nc_test/error.c b/test/nc_test/error.c
index 5bad4d8..7479428 100644
--- a/test/nc_test/error.c
+++ b/test/nc_test/error.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: error.c 1468 2013-10-26 16:53:18Z wkliao $
+ *  $Id: error.c 2551 2016-10-14 00:35:42Z wkliao $
  */
 
 #include <stddef.h>	/* because gcc 2.7.2.2 doesn't define size_t */
@@ -18,8 +18,8 @@ extern int  max_nmpt;		/* max. number of messages per test */
 /* Prototypes */
 void error(const char *fmt, ...);
 void print(const char *fmt, ...);
-int ifFail(const int expr, const int line, const char *file);
-void print_n_size_t(size_t nelems, const MPI_Offset *array);
+int ifFail(const int expr, const int line, const char *file, const char *func);
+void print_n_size_t(int nelems, const MPI_Offset *array);
 
 /*
  * Use for logging error conditions
@@ -53,11 +53,11 @@ print(const char *fmt, ...)
  * Called by macro IF
  */
 int
-ifFail(const int expr, const int line, const char *file)
+ifFail(const int expr, const int line, const char *file, const char *func)
 {
     if (expr) {
 	++nfails;
-	error("\n\tFAILURE at line %d of %s: ", line, file);
+	error("\n\tFAILURE at line %d of %s in %s: ", line, func, file);
     }
     return expr;
 }
@@ -67,7 +67,7 @@ ifFail(const int expr, const int line, const char *file)
  * "architecture" of this program.
  */
 void
-print_n_size_t(size_t nelems, const MPI_Offset *array)
+print_n_size_t(int nelems, const MPI_Offset *array)
 {
 	fprintf(stderr, "[");
 	while(nelems-- > 0)
diff --git a/test/nc_test/error.h b/test/nc_test/error.h
index 47e13b3..368b6bf 100644
--- a/test/nc_test/error.h
+++ b/test/nc_test/error.h
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: error.h 1468 2013-10-26 16:53:18Z wkliao $ */
+/* $Id: error.h 2551 2016-10-14 00:35:42Z wkliao $ */
 
 
 #ifdef __cplusplus
@@ -24,14 +24,14 @@ __attribute__ ((format (printf, 1, 2)))
 ;
 
 
-extern int ifFail(const int expr, const int line, const char *file);
+extern int ifFail(const int expr, const int line, const char *file, const char *func);
 
 extern void
-print_n_size_t(size_t nelems, const MPI_Offset *array);
+print_n_size_t(int nelems, const MPI_Offset *array);
 
 #ifdef __cplusplus
 }
 #endif
 
-#define IF(EXPR) if (ifFail(EXPR, __LINE__, __FILE__))
+#define IF(EXPR) if (ifFail(EXPR, __LINE__, __FILE__, __func__))
 #define ELSE_NOK else {nok++;}
diff --git a/test/nc_test/nc_test.c b/test/nc_test/nc_test.c
index a88bec5..5f63f48 100644
--- a/test/nc_test/nc_test.c
+++ b/test/nc_test/nc_test.c
@@ -2,18 +2,10 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: nc_test.c 2302 2016-01-10 20:33:45Z wkliao $
+ *  $Id: nc_test.c 2606 2016-11-10 19:19:45Z wkliao $
  */
 
 #include <unistd.h>
-
-int cdf_format;  /* 1: CDF-1, 2: CDF-2 5: CDF-5 */
-int extra_flags; /* if using CDF-2 format, will be set to NC_64BIT_OFFSET
-                    if using CDF-5 format, will be set to NC_64BIT_DATA */
-int numGatts;  /* number of global attributes */
-int numVars;   /* number of variables */
-int numTypes;  /* number of netCDF data types to test */
-
 #include "tests.h"
 
 /*
@@ -45,17 +37,17 @@ char dim_name[NDIMS][3];
 MPI_Offset dim_len[NDIMS];
 char var_name[NVARS][2+MAX_RANK];
 nc_type var_type[NVARS];
-size_t var_rank[NVARS];
+int var_rank[NVARS];
 int var_dimid[NVARS][MAX_RANK];
 MPI_Offset var_shape[NVARS][MAX_RANK];
-size_t var_nels[NVARS];
-size_t var_natts[NVARS];
+MPI_Offset var_nels[NVARS];
+int  var_natts[NVARS];
 char att_name[NVARS][MAX_NATTS][2];
 char gatt_name[NGATTS][3];
 nc_type att_type[NVARS][NGATTS];
 nc_type gatt_type[NGATTS];
-size_t att_len[NVARS][MAX_NATTS];
-size_t gatt_len[NGATTS];
+MPI_Offset att_len[NVARS][MAX_NATTS];
+MPI_Offset gatt_len[NGATTS];
 
 /* 
  * command-line options
@@ -87,26 +79,42 @@ usage(char *progname)
     error("   [-d directory] directory for storing input/output files\n");
 }
 
-#define NC_TEST(func) {                                                  \
-    char func_name[64];                                                  \
-    int noks;                                                            \
-    nfails = 0;                                                          \
-    sprintf(func_name, "test_%s",#func);                                 \
-    noks = test_ ## func();                                              \
+#define NC_CHECK_AND_PRINT                                               \
     nfailsTotal += nfails;                                               \
-    if (verbose && nfails == 0) {                                        \
-        if (verbose) printf( "*** Testing %-30s ... ",func_name);        \
-        if (noks > 0)                                                    \
-            printf("%4d good comparisons. ok\n", noks);                  \
-        else                                                             \
-            printf("\n");                                                \
+    if (verbose) print( "*** Testing %-30s ... ",func_name);             \
+    if (nfails == 0 && verbose) {                                        \
+        if (noks > 0) printf("%4d good comparisons. ok", noks);          \
+        printf("\n");                                                    \
     }                                                                    \
-    else if (nfails > 0) {                                               \
-        if (verbose) print( "*** Testing %-30s ... ",func_name);         \
+    if (nfails > 0) {                                                    \
         print("\n\t### %d FAILURES TESTING %s! Stop ... ###\n",          \
               nfails,func_name);                                         \
         goto fn_exit;                                                    \
-    }                                                                    \
+    }
+
+#define NC_TEST(func) {                                                  \
+    int noks;                                                            \
+    char func_name[64];                                                  \
+    nfails = 0;                                                          \
+    sprintf(func_name, "test_%s",#func);                                 \
+    noks = test_ ## func();                                              \
+    NC_CHECK_AND_PRINT                                                   \
+}
+
+#define NC_TEST1(func, arg) {                                            \
+    int noks;                                                            \
+    char func_name[64];                                                  \
+    sprintf(func_name, "test_%s",#func);                                 \
+    noks = test_ ## func(arg);                                           \
+    NC_CHECK_AND_PRINT                                                   \
+}
+
+#define NC_TEST2(func, arg1, arg2) {                                     \
+    int noks;                                                            \
+    char func_name[64];                                                  \
+    sprintf(func_name, "test_%s",#func);                                 \
+    noks = test_ ## func(arg1, arg2);                                    \
+    NC_CHECK_AND_PRINT                                                   \
 }
 
 #if 1		/* both CRAY MPP and OSF/1 Alpha systems need this */
@@ -117,8 +125,9 @@ int
 main(int argc, char *argv[])
 {
     extern char *optarg;
-    int c;
-    int  nfailsTotal = 0;        /* total number of failures */
+    int cdf_format, c;
+    int numGatts, numTypes, numVars;
+    int nfailsTotal = 0;        /* total number of failures */
 
 #if 1		/* both CRAY MPP and OSF/1 Alpha systems need this */
 	/*
@@ -131,7 +140,6 @@ main(int argc, char *argv[])
     MPI_Init(&argc, &argv);
 
     cdf_format = 1; 	/* 1: CDF-1, 2: CDF-2 5: CDF-5 */
-    extra_flags = 0;    /* NC_64BIT_OFFSET or NC_64BIT_DATA */
     create_file = 0;            /* file test.nc will normally already exist */
     read_only = 0;               /* assume may write in test dir as default */
     verbose = 0;
@@ -155,11 +163,9 @@ main(int argc, char *argv[])
 	  break;
 	case '2':
 	  cdf_format = 2;
-	  extra_flags = NC_64BIT_OFFSET;
 	  break;
 	case '5':
 	  cdf_format = 5;
-	  extra_flags = NC_64BIT_DATA;
 	case 'd':
           sprintf(testfile, "%s/test.nc", optarg);
           sprintf(scratch, "%s/scratch.nc", optarg);
@@ -182,11 +188,18 @@ main(int argc, char *argv[])
         numTypes = NTYPES;
     }
 
+    if (cdf_format == 2)
+        ncmpi_set_default_format(NC_FORMAT_CDF2, NULL);
+    else if (cdf_format == 5)
+        ncmpi_set_default_format(NC_FORMAT_CDF5, NULL);
+    else
+        ncmpi_set_default_format(NC_FORMAT_CLASSIC, NULL);
+
     /* Initialize global variables defining test file */
-    init_gvars();
+    init_gvars(numGatts, numTypes, numVars);
 
     if ( create_file ) {
-	write_file(testfile);
+	write_file(testfile, numGatts, numVars);
         MPI_Info_free(&info);
 	MPI_Finalize();
 	return nfailsTotal > 0;
@@ -206,332 +219,332 @@ main(int argc, char *argv[])
     NC_TEST(ncmpi_strerror);
     NC_TEST(ncmpi_open);
     NC_TEST(ncmpi_close);
-    NC_TEST(ncmpi_inq);
+    NC_TEST2(ncmpi_inq, numGatts, numVars);
     NC_TEST(ncmpi_inq_dimid);
     NC_TEST(ncmpi_inq_dim);
     NC_TEST(ncmpi_inq_dimlen);
     NC_TEST(ncmpi_inq_dimname);
-    NC_TEST(ncmpi_inq_varid);
-    NC_TEST(ncmpi_inq_var);
-    NC_TEST(ncmpi_inq_natts);
+    NC_TEST1(ncmpi_inq_varid, numVars);
+    NC_TEST1(ncmpi_inq_var, numVars);
+    NC_TEST1(ncmpi_inq_natts, numGatts);
     NC_TEST(ncmpi_inq_ndims);
-    NC_TEST(ncmpi_inq_nvars);
+    NC_TEST1(ncmpi_inq_nvars, numVars);
     NC_TEST(ncmpi_inq_unlimdim);
-    NC_TEST(ncmpi_inq_vardimid);
-    NC_TEST(ncmpi_inq_varname);
-    NC_TEST(ncmpi_inq_varnatts);
-    NC_TEST(ncmpi_inq_varndims);
-    NC_TEST(ncmpi_inq_vartype);
-    NC_TEST(ncmpi_get_var_text);
-    NC_TEST(ncmpi_get_var_schar);
-    NC_TEST(ncmpi_get_var_short);
-    NC_TEST(ncmpi_get_var_int);
-    NC_TEST(ncmpi_get_var_long); 
-    NC_TEST(ncmpi_get_var_float);
-    NC_TEST(ncmpi_get_var_double);
-    NC_TEST(ncmpi_get_var_uchar); 
-    NC_TEST(ncmpi_get_var_ushort);
-    NC_TEST(ncmpi_get_var_uint);
-    NC_TEST(ncmpi_get_var_longlong);
-    NC_TEST(ncmpi_get_var_ulonglong);
-    NC_TEST(ncmpi_get_var1_text);
-    NC_TEST(ncmpi_get_var1_schar);
-    NC_TEST(ncmpi_get_var1_short);
-    NC_TEST(ncmpi_get_var1_int);
-    NC_TEST(ncmpi_get_var1_long);
-    NC_TEST(ncmpi_get_var1_float);
-    NC_TEST(ncmpi_get_var1_double);
-    NC_TEST(ncmpi_get_var1_uchar); 
-    NC_TEST(ncmpi_get_var1_ushort);
-    NC_TEST(ncmpi_get_var1_uint);
-    NC_TEST(ncmpi_get_var1_longlong);
-    NC_TEST(ncmpi_get_var1_ulonglong);
-    NC_TEST(ncmpi_get_var1);
-    NC_TEST(ncmpi_get_vara_text);
-    NC_TEST(ncmpi_get_vara_schar);
-    NC_TEST(ncmpi_get_vara_short);
-    NC_TEST(ncmpi_get_vara_int);
-    NC_TEST(ncmpi_get_vara_long); 
-    NC_TEST(ncmpi_get_vara_float);
-    NC_TEST(ncmpi_get_vara_double);
-    NC_TEST(ncmpi_get_vara_uchar);
-    NC_TEST(ncmpi_get_vara_ushort);
-    NC_TEST(ncmpi_get_vara_uint);
-    NC_TEST(ncmpi_get_vara_longlong);
-    NC_TEST(ncmpi_get_vara_ulonglong);
-    NC_TEST(ncmpi_get_vara);
-    NC_TEST(ncmpi_get_vars_text);
-    NC_TEST(ncmpi_get_vars_schar);
-    NC_TEST(ncmpi_get_vars_short);
-    NC_TEST(ncmpi_get_vars_int);
-    NC_TEST(ncmpi_get_vars_long); 
-    NC_TEST(ncmpi_get_vars_float);
-    NC_TEST(ncmpi_get_vars_double);
-    NC_TEST(ncmpi_get_vars_uchar);
-    NC_TEST(ncmpi_get_vars_ushort);
-    NC_TEST(ncmpi_get_vars_uint);
-    NC_TEST(ncmpi_get_vars_longlong);
-    NC_TEST(ncmpi_get_vars_ulonglong);
-    NC_TEST(ncmpi_get_vars);
-    NC_TEST(ncmpi_get_varm_text);
-    NC_TEST(ncmpi_get_varm_schar);
-    NC_TEST(ncmpi_get_varm_short);
-    NC_TEST(ncmpi_get_varm_int);
-    NC_TEST(ncmpi_get_varm_long);
-    NC_TEST(ncmpi_get_varm_float);
-    NC_TEST(ncmpi_get_varm_double);
-    NC_TEST(ncmpi_get_varm_uchar);
-    NC_TEST(ncmpi_get_varm_ushort);
-    NC_TEST(ncmpi_get_varm_uint);
-    NC_TEST(ncmpi_get_varm_longlong);
-    NC_TEST(ncmpi_get_varm_ulonglong);
-    NC_TEST(ncmpi_get_varm);
-    NC_TEST(ncmpi_get_att_text);
-    NC_TEST(ncmpi_get_att_schar);
-    NC_TEST(ncmpi_get_att_short);
-    NC_TEST(ncmpi_get_att_int);
-    NC_TEST(ncmpi_get_att_long);
-    NC_TEST(ncmpi_get_att_float);
-    NC_TEST(ncmpi_get_att_double);
-    NC_TEST(ncmpi_get_att_uchar);
-    NC_TEST(ncmpi_get_att_ushort);
-    NC_TEST(ncmpi_get_att_uint);
-    NC_TEST(ncmpi_get_att_longlong);
-    NC_TEST(ncmpi_get_att_ulonglong);
-    NC_TEST(ncmpi_get_att);
-    NC_TEST(ncmpi_inq_att);
-    NC_TEST(ncmpi_inq_attname);
-    NC_TEST(ncmpi_inq_attid);
-    NC_TEST(ncmpi_inq_attlen);
-    NC_TEST(ncmpi_inq_atttype);
+    NC_TEST1(ncmpi_inq_vardimid, numVars);
+    NC_TEST1(ncmpi_inq_varname, numVars);
+    NC_TEST2(ncmpi_inq_varnatts, numGatts, numVars);
+    NC_TEST1(ncmpi_inq_varndims, numVars);
+    NC_TEST1(ncmpi_inq_vartype, numVars);
+    NC_TEST1(ncmpi_get_var_text, numVars);
+    NC_TEST1(ncmpi_get_var_schar, numVars);
+    NC_TEST1(ncmpi_get_var_short, numVars);
+    NC_TEST1(ncmpi_get_var_int, numVars);
+    NC_TEST1(ncmpi_get_var_long, numVars);
+    NC_TEST1(ncmpi_get_var_float, numVars);
+    NC_TEST1(ncmpi_get_var_double, numVars);
+    NC_TEST1(ncmpi_get_var_uchar, numVars);
+    NC_TEST1(ncmpi_get_var_ushort, numVars);
+    NC_TEST1(ncmpi_get_var_uint, numVars);
+    NC_TEST1(ncmpi_get_var_longlong, numVars);
+    NC_TEST1(ncmpi_get_var_ulonglong, numVars);
+    NC_TEST1(ncmpi_get_var1_text, numVars);
+    NC_TEST1(ncmpi_get_var1_schar, numVars);
+    NC_TEST1(ncmpi_get_var1_short, numVars);
+    NC_TEST1(ncmpi_get_var1_int, numVars);
+    NC_TEST1(ncmpi_get_var1_long, numVars);
+    NC_TEST1(ncmpi_get_var1_float, numVars);
+    NC_TEST1(ncmpi_get_var1_double, numVars);
+    NC_TEST1(ncmpi_get_var1_uchar, numVars);
+    NC_TEST1(ncmpi_get_var1_ushort, numVars);
+    NC_TEST1(ncmpi_get_var1_uint, numVars);
+    NC_TEST1(ncmpi_get_var1_longlong, numVars);
+    NC_TEST1(ncmpi_get_var1_ulonglong, numVars);
+    NC_TEST1(ncmpi_get_var1, numVars);
+    NC_TEST1(ncmpi_get_vara_text, numVars);
+    NC_TEST1(ncmpi_get_vara_schar, numVars);
+    NC_TEST1(ncmpi_get_vara_short, numVars);
+    NC_TEST1(ncmpi_get_vara_int, numVars);
+    NC_TEST1(ncmpi_get_vara_long, numVars);
+    NC_TEST1(ncmpi_get_vara_float, numVars);
+    NC_TEST1(ncmpi_get_vara_double, numVars);
+    NC_TEST1(ncmpi_get_vara_uchar, numVars);
+    NC_TEST1(ncmpi_get_vara_ushort, numVars);
+    NC_TEST1(ncmpi_get_vara_uint, numVars);
+    NC_TEST1(ncmpi_get_vara_longlong, numVars);
+    NC_TEST1(ncmpi_get_vara_ulonglong, numVars);
+    NC_TEST1(ncmpi_get_vara, numVars);
+    NC_TEST1(ncmpi_get_vars_text, numVars);
+    NC_TEST1(ncmpi_get_vars_schar, numVars);
+    NC_TEST1(ncmpi_get_vars_short, numVars);
+    NC_TEST1(ncmpi_get_vars_int, numVars);
+    NC_TEST1(ncmpi_get_vars_long, numVars);
+    NC_TEST1(ncmpi_get_vars_float, numVars);
+    NC_TEST1(ncmpi_get_vars_double, numVars);
+    NC_TEST1(ncmpi_get_vars_uchar, numVars);
+    NC_TEST1(ncmpi_get_vars_ushort, numVars);
+    NC_TEST1(ncmpi_get_vars_uint, numVars);
+    NC_TEST1(ncmpi_get_vars_longlong, numVars);
+    NC_TEST1(ncmpi_get_vars_ulonglong, numVars);
+    NC_TEST1(ncmpi_get_vars, numVars);
+    NC_TEST1(ncmpi_get_varm_text, numVars);
+    NC_TEST1(ncmpi_get_varm_schar, numVars);
+    NC_TEST1(ncmpi_get_varm_short, numVars);
+    NC_TEST1(ncmpi_get_varm_int, numVars);
+    NC_TEST1(ncmpi_get_varm_long, numVars);
+    NC_TEST1(ncmpi_get_varm_float, numVars);
+    NC_TEST1(ncmpi_get_varm_double, numVars);
+    NC_TEST1(ncmpi_get_varm_uchar, numVars);
+    NC_TEST1(ncmpi_get_varm_ushort, numVars);
+    NC_TEST1(ncmpi_get_varm_uint, numVars);
+    NC_TEST1(ncmpi_get_varm_longlong, numVars);
+    NC_TEST1(ncmpi_get_varm_ulonglong, numVars);
+    NC_TEST1(ncmpi_get_varm, numVars);
+    NC_TEST2(ncmpi_get_att_text, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_schar, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_short, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_int, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_long, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_float, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_double, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_uchar, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_ushort, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_uint, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_longlong, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att_ulonglong, numGatts, numVars);
+    NC_TEST2(ncmpi_get_att,     numGatts, numVars);
+    NC_TEST2(ncmpi_inq_att,     numGatts, numVars);
+    NC_TEST2(ncmpi_inq_attname, numGatts, numVars);
+    NC_TEST2(ncmpi_inq_attid,   numGatts, numVars);
+    NC_TEST2(ncmpi_inq_attlen,  numGatts, numVars);
+    NC_TEST2(ncmpi_inq_atttype, numGatts, numVars);
 
     /* nonblocking I/O */
-    NC_TEST(ncmpi_iget_var_text);
-    NC_TEST(ncmpi_iget_var_schar);
-    NC_TEST(ncmpi_iget_var_short);
-    NC_TEST(ncmpi_iget_var_int);
-    NC_TEST(ncmpi_iget_var_long); 
-    NC_TEST(ncmpi_iget_var_float);
-    NC_TEST(ncmpi_iget_var_double);
-    NC_TEST(ncmpi_iget_var_uchar); 
-    NC_TEST(ncmpi_iget_var_ushort);
-    NC_TEST(ncmpi_iget_var_uint);
-    NC_TEST(ncmpi_iget_var_longlong);
-    NC_TEST(ncmpi_iget_var_ulonglong);
-    NC_TEST(ncmpi_iget_var);
-    NC_TEST(ncmpi_iget_var1_text);
-    NC_TEST(ncmpi_iget_var1_schar);
-    NC_TEST(ncmpi_iget_var1_short);
-    NC_TEST(ncmpi_iget_var1_int);
-    NC_TEST(ncmpi_iget_var1_long);
-    NC_TEST(ncmpi_iget_var1_float);
-    NC_TEST(ncmpi_iget_var1_double);
-    NC_TEST(ncmpi_iget_var1_uchar); 
-    NC_TEST(ncmpi_iget_var1_ushort);
-    NC_TEST(ncmpi_iget_var1_uint);
-    NC_TEST(ncmpi_iget_var1_longlong);
-    NC_TEST(ncmpi_iget_var1_ulonglong);
-    NC_TEST(ncmpi_iget_var1);
-    NC_TEST(ncmpi_iget_vara_text);
-    NC_TEST(ncmpi_iget_vara_schar);
-    NC_TEST(ncmpi_iget_vara_short);
-    NC_TEST(ncmpi_iget_vara_int);
-    NC_TEST(ncmpi_iget_vara_long); 
-    NC_TEST(ncmpi_iget_vara_float);
-    NC_TEST(ncmpi_iget_vara_double);
-    NC_TEST(ncmpi_iget_vara_uchar);
-    NC_TEST(ncmpi_iget_vara_ushort);
-    NC_TEST(ncmpi_iget_vara_uint);
-    NC_TEST(ncmpi_iget_vara_longlong);
-    NC_TEST(ncmpi_iget_vara_ulonglong);
-    NC_TEST(ncmpi_iget_vara);
-    NC_TEST(ncmpi_iget_vars_text);
-    NC_TEST(ncmpi_iget_vars_schar);
-    NC_TEST(ncmpi_iget_vars_short);
-    NC_TEST(ncmpi_iget_vars_int);
-    NC_TEST(ncmpi_iget_vars_long); 
-    NC_TEST(ncmpi_iget_vars_float);
-    NC_TEST(ncmpi_iget_vars_double);
-    NC_TEST(ncmpi_iget_vars_uchar);
-    NC_TEST(ncmpi_iget_vars_ushort);
-    NC_TEST(ncmpi_iget_vars_uint);
-    NC_TEST(ncmpi_iget_vars_longlong);
-    NC_TEST(ncmpi_iget_vars_ulonglong);
-    NC_TEST(ncmpi_iget_vars);
-    NC_TEST(ncmpi_iget_varm_text);
-    NC_TEST(ncmpi_iget_varm_schar);
-    NC_TEST(ncmpi_iget_varm_short);
-    NC_TEST(ncmpi_iget_varm_int);
-    NC_TEST(ncmpi_iget_varm_long);
-    NC_TEST(ncmpi_iget_varm_float);
-    NC_TEST(ncmpi_iget_varm_double);
-    NC_TEST(ncmpi_iget_varm_uchar);
-    NC_TEST(ncmpi_iget_varm_ushort);
-    NC_TEST(ncmpi_iget_varm_uint);
-    NC_TEST(ncmpi_iget_varm_longlong);
-    NC_TEST(ncmpi_iget_varm_ulonglong);
-    NC_TEST(ncmpi_iget_varm);
+    NC_TEST1(ncmpi_iget_var_text, numVars);
+    NC_TEST1(ncmpi_iget_var_schar, numVars);
+    NC_TEST1(ncmpi_iget_var_short, numVars);
+    NC_TEST1(ncmpi_iget_var_int, numVars);
+    NC_TEST1(ncmpi_iget_var_long, numVars); 
+    NC_TEST1(ncmpi_iget_var_float, numVars);
+    NC_TEST1(ncmpi_iget_var_double, numVars);
+    NC_TEST1(ncmpi_iget_var_uchar, numVars); 
+    NC_TEST1(ncmpi_iget_var_ushort, numVars);
+    NC_TEST1(ncmpi_iget_var_uint, numVars);
+    NC_TEST1(ncmpi_iget_var_longlong, numVars);
+    NC_TEST1(ncmpi_iget_var_ulonglong, numVars);
+    NC_TEST1(ncmpi_iget_var, numVars);
+    NC_TEST1(ncmpi_iget_var1_text, numVars);
+    NC_TEST1(ncmpi_iget_var1_schar, numVars);
+    NC_TEST1(ncmpi_iget_var1_short, numVars);
+    NC_TEST1(ncmpi_iget_var1_int, numVars);
+    NC_TEST1(ncmpi_iget_var1_long, numVars);
+    NC_TEST1(ncmpi_iget_var1_float, numVars);
+    NC_TEST1(ncmpi_iget_var1_double, numVars);
+    NC_TEST1(ncmpi_iget_var1_uchar, numVars); 
+    NC_TEST1(ncmpi_iget_var1_ushort, numVars);
+    NC_TEST1(ncmpi_iget_var1_uint, numVars);
+    NC_TEST1(ncmpi_iget_var1_longlong, numVars);
+    NC_TEST1(ncmpi_iget_var1_ulonglong, numVars);
+    NC_TEST1(ncmpi_iget_var1, numVars);
+    NC_TEST1(ncmpi_iget_vara_text, numVars);
+    NC_TEST1(ncmpi_iget_vara_schar, numVars);
+    NC_TEST1(ncmpi_iget_vara_short, numVars);
+    NC_TEST1(ncmpi_iget_vara_int, numVars);
+    NC_TEST1(ncmpi_iget_vara_long, numVars); 
+    NC_TEST1(ncmpi_iget_vara_float, numVars);
+    NC_TEST1(ncmpi_iget_vara_double, numVars);
+    NC_TEST1(ncmpi_iget_vara_uchar, numVars);
+    NC_TEST1(ncmpi_iget_vara_ushort, numVars);
+    NC_TEST1(ncmpi_iget_vara_uint, numVars);
+    NC_TEST1(ncmpi_iget_vara_longlong, numVars);
+    NC_TEST1(ncmpi_iget_vara_ulonglong, numVars);
+    NC_TEST1(ncmpi_iget_vara, numVars);
+    NC_TEST1(ncmpi_iget_vars_text, numVars);
+    NC_TEST1(ncmpi_iget_vars_schar, numVars);
+    NC_TEST1(ncmpi_iget_vars_short, numVars);
+    NC_TEST1(ncmpi_iget_vars_int, numVars);
+    NC_TEST1(ncmpi_iget_vars_long, numVars); 
+    NC_TEST1(ncmpi_iget_vars_float, numVars);
+    NC_TEST1(ncmpi_iget_vars_double, numVars);
+    NC_TEST1(ncmpi_iget_vars_uchar, numVars);
+    NC_TEST1(ncmpi_iget_vars_ushort, numVars);
+    NC_TEST1(ncmpi_iget_vars_uint, numVars);
+    NC_TEST1(ncmpi_iget_vars_longlong, numVars);
+    NC_TEST1(ncmpi_iget_vars_ulonglong, numVars);
+    NC_TEST1(ncmpi_iget_vars, numVars);
+    NC_TEST1(ncmpi_iget_varm_text, numVars);
+    NC_TEST1(ncmpi_iget_varm_schar, numVars);
+    NC_TEST1(ncmpi_iget_varm_short, numVars);
+    NC_TEST1(ncmpi_iget_varm_int, numVars);
+    NC_TEST1(ncmpi_iget_varm_long, numVars);
+    NC_TEST1(ncmpi_iget_varm_float, numVars);
+    NC_TEST1(ncmpi_iget_varm_double, numVars);
+    NC_TEST1(ncmpi_iget_varm_uchar, numVars);
+    NC_TEST1(ncmpi_iget_varm_ushort, numVars);
+    NC_TEST1(ncmpi_iget_varm_uint, numVars);
+    NC_TEST1(ncmpi_iget_varm_longlong, numVars);
+    NC_TEST1(ncmpi_iget_varm_ulonglong, numVars);
+    NC_TEST1(ncmpi_iget_varm, numVars);
 
 	/* Test write functions */
     if (! read_only) {
 	NC_TEST(ncmpi_create);
-	NC_TEST(ncmpi_redef);
+	NC_TEST2(ncmpi_redef, numGatts, numVars);
 	/* NC_TEST(ncmpi_enddef);  redundant, as it calls test_ncmpi_redef() */
-	NC_TEST(ncmpi_sync);
-	NC_TEST(ncmpi_abort);
-	NC_TEST(ncmpi_def_dim);
+	NC_TEST2(ncmpi_sync, numGatts, numVars);
+	NC_TEST2(ncmpi_abort, numGatts, numVars);
+	NC_TEST1(ncmpi_def_dim, numVars);
 	NC_TEST(ncmpi_rename_dim);
-	NC_TEST(ncmpi_def_var);
-	NC_TEST(ncmpi_put_var_text);
-	NC_TEST(ncmpi_put_var_schar);
-	NC_TEST(ncmpi_put_var_short);
-	NC_TEST(ncmpi_put_var_int);
-	NC_TEST(ncmpi_put_var_long); 
-	NC_TEST(ncmpi_put_var_float);
-	NC_TEST(ncmpi_put_var_double);
-	NC_TEST(ncmpi_put_var_uchar);
-	NC_TEST(ncmpi_put_var_ushort);
-	NC_TEST(ncmpi_put_var_uint);
-	NC_TEST(ncmpi_put_var_longlong);
-	NC_TEST(ncmpi_put_var_ulonglong);
-	NC_TEST(ncmpi_put_var1_text);
-	NC_TEST(ncmpi_put_var1_schar);
-	NC_TEST(ncmpi_put_var1_short);
-	NC_TEST(ncmpi_put_var1_int);
-	NC_TEST(ncmpi_put_var1_long); 
-	NC_TEST(ncmpi_put_var1_float);
-	NC_TEST(ncmpi_put_var1_double);
-	NC_TEST(ncmpi_put_var1_uchar); 
-	NC_TEST(ncmpi_put_var1_ushort);
-	NC_TEST(ncmpi_put_var1_uint);
-	NC_TEST(ncmpi_put_var1_longlong);
-	NC_TEST(ncmpi_put_var1_ulonglong);
-	NC_TEST(ncmpi_put_var1);
-	NC_TEST(ncmpi_put_vara_text);
-	NC_TEST(ncmpi_put_vara_schar); 
-	NC_TEST(ncmpi_put_vara_short);
-	NC_TEST(ncmpi_put_vara_int);
-	NC_TEST(ncmpi_put_vara_long);
-	NC_TEST(ncmpi_put_vara_float);
-	NC_TEST(ncmpi_put_vara_double);
-	NC_TEST(ncmpi_put_vara_uchar);
-	NC_TEST(ncmpi_put_vara_ushort);
-	NC_TEST(ncmpi_put_vara_uint);
-	NC_TEST(ncmpi_put_vara_longlong);
-	NC_TEST(ncmpi_put_vara_ulonglong);
-	NC_TEST(ncmpi_put_vara);
-	NC_TEST(ncmpi_put_vars_text);
-	NC_TEST(ncmpi_put_vars_schar);
-	NC_TEST(ncmpi_put_vars_short);
-	NC_TEST(ncmpi_put_vars_int);
-	NC_TEST(ncmpi_put_vars_long); 
-	NC_TEST(ncmpi_put_vars_float);
-	NC_TEST(ncmpi_put_vars_double);
-	NC_TEST(ncmpi_put_vars_uchar);
-	NC_TEST(ncmpi_put_vars_ushort);
-	NC_TEST(ncmpi_put_vars_uint);
-	NC_TEST(ncmpi_put_vars_longlong);
-	NC_TEST(ncmpi_put_vars_ulonglong);
-	NC_TEST(ncmpi_put_vars);
-	NC_TEST(ncmpi_put_varm_text);
-	NC_TEST(ncmpi_put_varm_schar);
-	NC_TEST(ncmpi_put_varm_short);
-	NC_TEST(ncmpi_put_varm_int);
-	NC_TEST(ncmpi_put_varm_long);
-	NC_TEST(ncmpi_put_varm_float);
-	NC_TEST(ncmpi_put_varm_double);
-	NC_TEST(ncmpi_put_varm_uchar);
-	NC_TEST(ncmpi_put_varm_ushort);
-	NC_TEST(ncmpi_put_varm_uint);
-	NC_TEST(ncmpi_put_varm_longlong);
-	NC_TEST(ncmpi_put_varm_ulonglong);
-	NC_TEST(ncmpi_put_varm);
-	NC_TEST(ncmpi_rename_var);
-	NC_TEST(ncmpi_put_att_text);
-	NC_TEST(ncmpi_put_att_schar);
-	NC_TEST(ncmpi_put_att_short);
-	NC_TEST(ncmpi_put_att_int);
-	NC_TEST(ncmpi_put_att_long);
-	NC_TEST(ncmpi_put_att_float);
-	NC_TEST(ncmpi_put_att_double);
-	NC_TEST(ncmpi_put_att_uchar);
-	NC_TEST(ncmpi_put_att_ushort);
-	NC_TEST(ncmpi_put_att_uint);
-	NC_TEST(ncmpi_put_att_longlong);
-	NC_TEST(ncmpi_put_att_ulonglong);
-	NC_TEST(ncmpi_put_att);
-	NC_TEST(ncmpi_copy_att);
-	NC_TEST(ncmpi_rename_att);
-	NC_TEST(ncmpi_del_att);
-	NC_TEST(ncmpi_set_fill);
+	NC_TEST1(ncmpi_def_var, numVars);
+	NC_TEST1(ncmpi_put_var_text, numVars);
+	NC_TEST1(ncmpi_put_var_schar, numVars);
+	NC_TEST1(ncmpi_put_var_short, numVars);
+	NC_TEST1(ncmpi_put_var_int, numVars);
+	NC_TEST1(ncmpi_put_var_long, numVars);
+	NC_TEST1(ncmpi_put_var_float, numVars);
+	NC_TEST1(ncmpi_put_var_double, numVars);
+	NC_TEST1(ncmpi_put_var_uchar, numVars);
+	NC_TEST1(ncmpi_put_var_ushort, numVars);
+	NC_TEST1(ncmpi_put_var_uint, numVars);
+	NC_TEST1(ncmpi_put_var_longlong, numVars);
+	NC_TEST1(ncmpi_put_var_ulonglong, numVars);
+	NC_TEST1(ncmpi_put_var1_text, numVars);
+	NC_TEST1(ncmpi_put_var1_schar, numVars);
+	NC_TEST1(ncmpi_put_var1_short, numVars);
+	NC_TEST1(ncmpi_put_var1_int, numVars);
+	NC_TEST1(ncmpi_put_var1_long, numVars);
+	NC_TEST1(ncmpi_put_var1_float, numVars);
+	NC_TEST1(ncmpi_put_var1_double, numVars);
+	NC_TEST1(ncmpi_put_var1_uchar, numVars);
+	NC_TEST1(ncmpi_put_var1_ushort, numVars);
+	NC_TEST1(ncmpi_put_var1_uint, numVars);
+	NC_TEST1(ncmpi_put_var1_longlong, numVars);
+	NC_TEST1(ncmpi_put_var1_ulonglong, numVars);
+	NC_TEST1(ncmpi_put_var1, numVars);
+	NC_TEST1(ncmpi_put_vara_text, numVars);
+	NC_TEST1(ncmpi_put_vara_schar, numVars);
+	NC_TEST1(ncmpi_put_vara_short, numVars);
+	NC_TEST1(ncmpi_put_vara_int, numVars);
+	NC_TEST1(ncmpi_put_vara_long, numVars);
+	NC_TEST1(ncmpi_put_vara_float, numVars);
+	NC_TEST1(ncmpi_put_vara_double, numVars);
+	NC_TEST1(ncmpi_put_vara_uchar, numVars);
+	NC_TEST1(ncmpi_put_vara_ushort, numVars);
+	NC_TEST1(ncmpi_put_vara_uint, numVars);
+	NC_TEST1(ncmpi_put_vara_longlong, numVars);
+	NC_TEST1(ncmpi_put_vara_ulonglong, numVars);
+	NC_TEST1(ncmpi_put_vara, numVars);
+	NC_TEST1(ncmpi_put_vars_text, numVars);
+	NC_TEST1(ncmpi_put_vars_schar, numVars);
+	NC_TEST1(ncmpi_put_vars_short, numVars);
+	NC_TEST1(ncmpi_put_vars_int, numVars);
+	NC_TEST1(ncmpi_put_vars_long, numVars);
+	NC_TEST1(ncmpi_put_vars_float, numVars);
+	NC_TEST1(ncmpi_put_vars_double, numVars);
+	NC_TEST1(ncmpi_put_vars_uchar, numVars);
+	NC_TEST1(ncmpi_put_vars_ushort, numVars);
+	NC_TEST1(ncmpi_put_vars_uint, numVars);
+	NC_TEST1(ncmpi_put_vars_longlong, numVars);
+	NC_TEST1(ncmpi_put_vars_ulonglong, numVars);
+	NC_TEST1(ncmpi_put_vars, numVars);
+	NC_TEST1(ncmpi_put_varm_text, numVars);
+	NC_TEST1(ncmpi_put_varm_schar, numVars);
+	NC_TEST1(ncmpi_put_varm_short, numVars);
+	NC_TEST1(ncmpi_put_varm_int, numVars);
+	NC_TEST1(ncmpi_put_varm_long, numVars);
+	NC_TEST1(ncmpi_put_varm_float, numVars);
+	NC_TEST1(ncmpi_put_varm_double, numVars);
+	NC_TEST1(ncmpi_put_varm_uchar, numVars);
+	NC_TEST1(ncmpi_put_varm_ushort, numVars);
+	NC_TEST1(ncmpi_put_varm_uint, numVars);
+	NC_TEST1(ncmpi_put_varm_longlong, numVars);
+	NC_TEST1(ncmpi_put_varm_ulonglong, numVars);
+	NC_TEST1(ncmpi_put_varm, numVars);
+	NC_TEST1(ncmpi_rename_var, numVars);
+	NC_TEST2(ncmpi_put_att_text, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_schar, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_short, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_int, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_long, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_float, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_double, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_uchar, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_ushort, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_uint, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_longlong, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att_ulonglong, numGatts, numVars);
+	NC_TEST2(ncmpi_put_att, numGatts, numVars);
+	NC_TEST2(ncmpi_copy_att, numGatts, numVars);
+	NC_TEST2(ncmpi_rename_att, numGatts, numVars);
+	NC_TEST2(ncmpi_del_att, numGatts, numVars);
+	NC_TEST1(ncmpi_set_fill, numVars);
 	NC_TEST(ncmpi_delete);
 
         /* test nonblocking APIs */
-	NC_TEST(ncmpi_iput_var_text);
-	NC_TEST(ncmpi_iput_var_schar);
-	NC_TEST(ncmpi_iput_var_short);
-	NC_TEST(ncmpi_iput_var_int);
-	NC_TEST(ncmpi_iput_var_long); 
-	NC_TEST(ncmpi_iput_var_float);
-	NC_TEST(ncmpi_iput_var_double);
-	NC_TEST(ncmpi_iput_var_uchar);
-	NC_TEST(ncmpi_iput_var_ushort);
-	NC_TEST(ncmpi_iput_var_uint);
-	NC_TEST(ncmpi_iput_var_longlong);
-	NC_TEST(ncmpi_iput_var_ulonglong);
-	NC_TEST(ncmpi_iput_var);
-	NC_TEST(ncmpi_iput_var1_text);
-	NC_TEST(ncmpi_iput_var1_schar);
-	NC_TEST(ncmpi_iput_var1_short);
-	NC_TEST(ncmpi_iput_var1_int);
-	NC_TEST(ncmpi_iput_var1_long); 
-	NC_TEST(ncmpi_iput_var1_float);
-	NC_TEST(ncmpi_iput_var1_double);
-	NC_TEST(ncmpi_iput_var1_uchar); 
-	NC_TEST(ncmpi_iput_var1_ushort);
-	NC_TEST(ncmpi_iput_var1_uint);
-	NC_TEST(ncmpi_iput_var1_longlong);
-	NC_TEST(ncmpi_iput_var1_ulonglong);
-	NC_TEST(ncmpi_iput_var1);
-	NC_TEST(ncmpi_iput_vara_text);
-	NC_TEST(ncmpi_iput_vara_schar); 
-	NC_TEST(ncmpi_iput_vara_short);
-	NC_TEST(ncmpi_iput_vara_int);
-	NC_TEST(ncmpi_iput_vara_long);
-	NC_TEST(ncmpi_iput_vara_float);
-	NC_TEST(ncmpi_iput_vara_double);
-	NC_TEST(ncmpi_iput_vara_uchar);
-	NC_TEST(ncmpi_iput_vara_ushort);
-	NC_TEST(ncmpi_iput_vara_uint);
-	NC_TEST(ncmpi_iput_vara_longlong);
-	NC_TEST(ncmpi_iput_vara_ulonglong);
-	NC_TEST(ncmpi_iput_vara);
-	NC_TEST(ncmpi_iput_vars_text);
-	NC_TEST(ncmpi_iput_vars_schar);
-	NC_TEST(ncmpi_iput_vars_short);
-	NC_TEST(ncmpi_iput_vars_int);
-	NC_TEST(ncmpi_iput_vars_long); 
-	NC_TEST(ncmpi_iput_vars_float);
-	NC_TEST(ncmpi_iput_vars_double);
-	NC_TEST(ncmpi_iput_vars_uchar);
-	NC_TEST(ncmpi_iput_vars_ushort);
-	NC_TEST(ncmpi_iput_vars_uint);
-	NC_TEST(ncmpi_iput_vars_longlong);
-	NC_TEST(ncmpi_iput_vars_ulonglong);
-	NC_TEST(ncmpi_iput_vars);
-	NC_TEST(ncmpi_iput_varm_text);
-	NC_TEST(ncmpi_iput_varm_schar);
-	NC_TEST(ncmpi_iput_varm_short);
-	NC_TEST(ncmpi_iput_varm_int);
-	NC_TEST(ncmpi_iput_varm_long);
-	NC_TEST(ncmpi_iput_varm_float);
-	NC_TEST(ncmpi_iput_varm_double);
-	NC_TEST(ncmpi_iput_varm_uchar);
-	NC_TEST(ncmpi_iput_varm_ushort);
-	NC_TEST(ncmpi_iput_varm_uint);
-	NC_TEST(ncmpi_iput_varm_longlong);
-	NC_TEST(ncmpi_iput_varm_ulonglong);
-	NC_TEST(ncmpi_iput_varm);
+	NC_TEST1(ncmpi_iput_var_text, numVars);
+	NC_TEST1(ncmpi_iput_var_schar, numVars);
+	NC_TEST1(ncmpi_iput_var_short, numVars);
+	NC_TEST1(ncmpi_iput_var_int, numVars);
+	NC_TEST1(ncmpi_iput_var_long, numVars);
+	NC_TEST1(ncmpi_iput_var_float, numVars);
+	NC_TEST1(ncmpi_iput_var_double, numVars);
+	NC_TEST1(ncmpi_iput_var_uchar, numVars);
+	NC_TEST1(ncmpi_iput_var_ushort, numVars);
+	NC_TEST1(ncmpi_iput_var_uint, numVars);
+	NC_TEST1(ncmpi_iput_var_longlong, numVars);
+	NC_TEST1(ncmpi_iput_var_ulonglong, numVars);
+	NC_TEST1(ncmpi_iput_var, numVars);
+	NC_TEST1(ncmpi_iput_var1_text, numVars);
+	NC_TEST1(ncmpi_iput_var1_schar, numVars);
+	NC_TEST1(ncmpi_iput_var1_short, numVars);
+	NC_TEST1(ncmpi_iput_var1_int, numVars);
+	NC_TEST1(ncmpi_iput_var1_long, numVars);
+	NC_TEST1(ncmpi_iput_var1_float, numVars);
+	NC_TEST1(ncmpi_iput_var1_double, numVars);
+	NC_TEST1(ncmpi_iput_var1_uchar, numVars);
+	NC_TEST1(ncmpi_iput_var1_ushort, numVars);
+	NC_TEST1(ncmpi_iput_var1_uint, numVars);
+	NC_TEST1(ncmpi_iput_var1_longlong, numVars);
+	NC_TEST1(ncmpi_iput_var1_ulonglong, numVars);
+	NC_TEST1(ncmpi_iput_var1, numVars);
+	NC_TEST1(ncmpi_iput_vara_text, numVars);
+	NC_TEST1(ncmpi_iput_vara_schar, numVars);
+	NC_TEST1(ncmpi_iput_vara_short, numVars);
+	NC_TEST1(ncmpi_iput_vara_int, numVars);
+	NC_TEST1(ncmpi_iput_vara_long, numVars);
+	NC_TEST1(ncmpi_iput_vara_float, numVars);
+	NC_TEST1(ncmpi_iput_vara_double, numVars);
+	NC_TEST1(ncmpi_iput_vara_uchar, numVars);
+	NC_TEST1(ncmpi_iput_vara_ushort, numVars);
+	NC_TEST1(ncmpi_iput_vara_uint, numVars);
+	NC_TEST1(ncmpi_iput_vara_longlong, numVars);
+	NC_TEST1(ncmpi_iput_vara_ulonglong, numVars);
+	NC_TEST1(ncmpi_iput_vara, numVars);
+	NC_TEST1(ncmpi_iput_vars_text, numVars);
+	NC_TEST1(ncmpi_iput_vars_schar, numVars);
+	NC_TEST1(ncmpi_iput_vars_short, numVars);
+	NC_TEST1(ncmpi_iput_vars_int, numVars);
+	NC_TEST1(ncmpi_iput_vars_long, numVars);
+	NC_TEST1(ncmpi_iput_vars_float, numVars);
+	NC_TEST1(ncmpi_iput_vars_double, numVars);
+	NC_TEST1(ncmpi_iput_vars_uchar, numVars);
+	NC_TEST1(ncmpi_iput_vars_ushort, numVars);
+	NC_TEST1(ncmpi_iput_vars_uint, numVars);
+	NC_TEST1(ncmpi_iput_vars_longlong, numVars);
+	NC_TEST1(ncmpi_iput_vars_ulonglong, numVars);
+	NC_TEST1(ncmpi_iput_vars, numVars);
+	NC_TEST1(ncmpi_iput_varm_text, numVars);
+	NC_TEST1(ncmpi_iput_varm_schar, numVars);
+	NC_TEST1(ncmpi_iput_varm_short, numVars);
+	NC_TEST1(ncmpi_iput_varm_int, numVars);
+	NC_TEST1(ncmpi_iput_varm_long, numVars);
+	NC_TEST1(ncmpi_iput_varm_float, numVars);
+	NC_TEST1(ncmpi_iput_varm_double, numVars);
+	NC_TEST1(ncmpi_iput_varm_uchar, numVars);
+	NC_TEST1(ncmpi_iput_varm_ushort, numVars);
+	NC_TEST1(ncmpi_iput_varm_uint, numVars);
+	NC_TEST1(ncmpi_iput_varm_longlong, numVars);
+	NC_TEST1(ncmpi_iput_varm_ulonglong, numVars);
+	NC_TEST1(ncmpi_iput_varm, numVars);
     }
 
 fn_exit:
diff --git a/test/nc_test/test_get.m4 b/test/nc_test/test_get.m4
index ac393f3..f3b1366 100644
--- a/test/nc_test/test_get.m4
+++ b/test/nc_test/test_get.m4
@@ -1,6 +1,8 @@
 dnl This is m4 source.
 dnl Process using m4 to produce 'C' language file.
 dnl
+dnl This file is supposed to be the same as PnetCDF's test_get.m4
+dnl
 dnl If you see this line, you can ignore the next one.
 /* Do not edit this file. It is produced from the corresponding .m4 source */
 dnl
@@ -8,8 +10,35 @@ dnl
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: test_get.m4 2311 2016-01-30 01:01:40Z wkliao $ */
+/* $Id: test_get.m4 2611 2016-11-11 19:26:14Z wkliao $ */
+
+dnl
+dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
+dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types
+dnl (MPI_Offset vs. size_t), and function name substrings for external data
+dnl types.
+dnl
+
+#include "tests.h"
+
+define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl
 
+define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl
+define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl
+define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_get_$1',`test_nc_get_$1')')dnl
+define(`APIFunc',` ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl
+
+define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, &ncid)', `file_open($1, $2, &ncid)')')dnl
+
+define(`VarArgs',   `ifdef(`PNETCDF',`int numVars',`void')')dnl
+define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts,int numVars',`void')')dnl
+
+define(`GetVar1',`ifdef(`PNETCDF',`ncmpi_get_var1_$1_all',`nc_get_var1_$1')')dnl
+define(`GetVar', `ifdef(`PNETCDF',`ncmpi_get_var_$1_all', `nc_get_var_$1')')dnl
+define(`GetVara',`ifdef(`PNETCDF',`ncmpi_get_vara_$1_all',`nc_get_vara_$1')')dnl
+define(`GetVars',`ifdef(`PNETCDF',`ncmpi_get_vars_$1_all',`nc_get_vars_$1')')dnl
+define(`GetVarm',`ifdef(`PNETCDF',`ncmpi_get_varm_$1_all',`nc_get_varm_$1')')dnl
+define(`GetAtt', `ifdef(`PNETCDF',`ncmpi_get_att_$1',`nc_get_att_$1')')dnl
 
 undefine(`index')dnl
 dnl dnl dnl
@@ -33,107 +62,137 @@ dnl
 define(`CheckText', `ifelse(`$1',`text', , `== (NCT_ITYPE($1) == NCT_TEXT)')')dnl
 define(`CheckRange',`ifelse(`$1',`text', `1', `($2 >= $1_min && $2 <= $1_max)')')dnl
 define(`IfCheckTextChar', `ifelse(`$1',`text', `if ($2 != NC_CHAR)')')dnl
-define(`CheckNumRange',
-       `ifelse(`$1',`text', `1',
-               `inRange3($2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
-
-#include "tests.h"
+define(`CheckNumRange',`ifelse(`$1',`text', `1',`inRange3(cdf_format, $2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
 
 dnl TEST_NC_GET_VAR1(TYPE)
 dnl
 define(`TEST_NC_GET_VAR1',dnl
 `dnl
 int
-test_ncmpi_get_var1_$1(void)
+TestFunc(var1)_$1(VarArgs)
 {
-    int ncid;
-    int i;
-    int j;
-    int err;
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset index[MAX_RANK];
+    int i, err, ncid, cdf_format;
+    int nok = 0;        /* count of valid comparisons */
     int canConvert;     /* Both text or both numeric */
+    IntType j, index[MAX_RANK];
     double expect;
-    $1 value;
+    $1 value[1];
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = GetVar1($1)(BAD_ID, 0, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = GetVar1($1)(ncid, BAD_VARID, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
-    ncmpi_begin_indep_data(ncid);
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
-        for (j = 0; j < var_rank[i]; j++)
-            index[j] = 0;
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
 
-        /* check if pnetcdf can detect a bad file ID */
-        err = ncmpi_get_var1_$1(BAD_ID, i, index, &value);
+        /* check if can detect a bad file ID */
+        err = GetVar1($1)(BAD_ID, i, NULL, value);
         IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = GetVar1($1)(ncid, i, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) {
+            index[0] = 0;
+            expect = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect, var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect)) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+')dnl
 
-        /* check if pnetcdf can detect a bad variable ID */
-        err = ncmpi_get_var1_$1(ncid, BAD_VARID, index, &value);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+        /* test NC_EINVALCOORDS */
+        for (j = 0; j < var_rank[i]; j++) index[j] = 0;
 
-        /* check if pnetcdf can detect out of boundary requests */
         for (j = 0; j < var_rank[i]; j++) {
-            index[j] = var_shape[i][j]; /* make an out-of-boundary starts[] */
-            err = ncmpi_get_var1_$1(ncid, i, index, &value);
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            index[j] = var_shape[i][j];     /* out of boundary check */
+            err = GetVar1($1)(ncid, i, index, value);
             if (!canConvert) {
                 IF (err != NC_ECHAR)
-                    error("conversion: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
             } else IF (err != NC_EINVALCOORDS)
-                error("bad index: err = %d", err);
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
             index[j] = 0;
         }
 
         /* check if the contents are supposed to be */
         for (j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR)
-                error("error in toMixedBase 1");
-
+            IF (err != 0) error("error in toMixedBase");
             /* when file is created the variable contents are generated by
              * hash functions */
-            expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1) );
-
-            if (var_rank[i] == 0 && i%2 )
-                /* this var has no dim, a scalar variable */
-                err = ncmpi_get_var1_$1(ncid, i, NULL, &value);
-            else
-                err = ncmpi_get_var1_$1(ncid, i, index, &value);
-
+            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
+                           NCT_ITYPE($1));
+            err = GetVar1($1)(ncid, i, index, value);
             if (canConvert) {
-                if (inRange3(expect,var_type[i], NCT_ITYPE($1))) {
+                if (inRange3(cdf_format, expect,var_type[i], NCT_ITYPE($1))) {
                     if (CheckRange($1, expect)) {
                         IF (err != NC_NOERR) {
-                            error("%s", ncmpi_strerror(err));
+                            EXPECT_ERR(NC_NOERR, err)
                         } else {
-                            IF (!equal(value,expect,var_type[i],NCT_ITYPE($1))) {
-                                error("expected: %G, got: %G", expect, (double) value);
-                            } else {
-                                nok++;
+                            ifelse(`$1', `uchar', `
+                            /* in put_vars(), API _put_vara_double() is used to
+                             * write the NC_BYTE variables to files. In this
+                             * case, NC_BYTE variables are treated as signed
+                             * for CDF-1 and 2 formats. Thus, we must skip the
+                             * equal test below for uchar.
+                             */
+                            if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect > schar_max) continue;')
+                            IF (!equal((double)value[0], expect, var_type[i], NCT_ITYPE($1))) {
+                                error("expected: %G, got: %G", expect, (double)value[0]);
                             }
+                            ELSE_NOK
                         }
                     } else {
                         IF (err != NC_ERANGE)
-                            error("Range error: err = %d", err);
+                            EXPECT_ERR(NC_ERANGE, err)
+                        ELSE_NOK
                     }
                 } else {
                     IF (err != NC_NOERR && err != NC_ERANGE)
-                        error("OK or Range error: err = %d", err);
+                        EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
                 }
             } else {
                 IF (err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
             }
         }
     }
-    ncmpi_end_indep_data(ncid);
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
@@ -157,75 +216,84 @@ dnl
 define(`TEST_NC_GET_VAR',dnl
 `dnl
 int
-test_ncmpi_get_var_$1(void)
+TestFunc(var)_$1(VarArgs)
 {
-    int ncid;
-    int i;
-    int j;
-    int err;
+    int i, err, ncid, cdf_format;
     int allInExtRange;  /* all values within range of external data type */
     int allInIntRange;  /* all values within range of internal data type */
-    int nels;
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset index[MAX_RANK];
+    int nok = 0;        /* count of valid comparisons */
     int canConvert;     /* Both text or both numeric */
+    IntType j, index[MAX_RANK];
     double expect[MAX_NELS];
     $1 value[MAX_NELS];
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = GetVar($1)(BAD_ID, 0, value);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = GetVar($1)(ncid, BAD_VARID, value);
+    IF (err != NC_ENOTVAR)
+        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
 
-        /* check if pnetcdf can detect a bad file ID */
-        err = ncmpi_get_var_$1_all(BAD_ID, i, value);
+        /* check if can detect a bad file ID */
+        err = GetVar($1)(BAD_ID, i, value);
         IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
 
-        /* check if pnetcdf can detect a bad variable ID */
-        err = ncmpi_get_var_$1_all(ncid, BAD_VARID, value);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
 
-        /* check if the contents are supposed to be */
-        nels = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            nels *= var_shape[i][j];
-        }
         allInExtRange = allInIntRange = 1;
-        for (j = 0; j < nels; j++) {
+        for (j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR)
-                error("error in toMixedBase 1");
-            expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1));
-            if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) {
+            IF (err != 0) error("error in toMixedBase");
+            expect[j] = hash4(cdf_format, var_type[i], var_rank[i], index,
+                              NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[j],var_type[i], NCT_ITYPE($1))) {
                 IfCheckTextChar($1, var_type[i])
                     allInIntRange &= CheckRange($1,expect[j]);
-            } else {
+            } else
                 allInExtRange = 0;
-            }
         }
-        err = ncmpi_get_var_$1_all(ncid, i, value);
+        err = GetVar($1)(ncid, i, value);
         if (canConvert) {
             if (allInExtRange) {
                 if (allInIntRange) {
                     IF (err != NC_NOERR)
-                        error("(%s) %s", ncmpii_err_code_name(err),ncmpi_strerror(err));
+                        EXPECT_ERR(NC_NOERR, err)
                 } else {
                     IF (err != NC_ERANGE)
-                        error("Range error: err = %d", err);
+                        EXPECT_ERR(NC_ERANGE, err)
                 }
             } else {
                 IF (err != NC_NOERR && err != NC_ERANGE)
-                    error("OK or Range error: err = %d", err);
+                    EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
             }
-            for (j = 0; j < nels; j++) {
+            for (j = 0; j < var_nels[i]; j++) {
                 if (CheckNumRange($1, expect[j], var_type[i])) {
-                    IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){
+                    ifelse(`$1', `uchar', `
+                    /* in put_vars(), API _put_vara_double() is used to
+                     * write the NC_BYTE variables to files. In this
+                     * case, NC_BYTE variables are treated as signed
+                     * for CDF-1 and 2 formats. Thus, we must skip the
+                     * equal test below for uchar.
+                     */
+                    if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
+                    IF (!equal((double)value[j],expect[j],var_type[i],NCT_ITYPE($1))){
                         error("value read not that expected");
                         if (verbose) {
                             error("\n");
@@ -236,19 +304,19 @@ test_ncmpi_get_var_$1(void)
                             error("expect: %g, ", expect[j]);
                             error("got: %g", (double) value[j]);
                         }
-                    } else {
-                        nok++;
                     }
+                    ELSE_NOK
                 }
             }
         } else {
-            IF (nels > 0 && err != NC_ECHAR)
-                error("wrong type: err = %d", err);
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
@@ -272,89 +340,158 @@ dnl
 define(`TEST_NC_GET_VARA',dnl
 `dnl
 int
-test_ncmpi_get_vara_$1(void)
+TestFunc(vara)_$1(VarArgs)
 {
-    int ncid;
-    int d;
-    int i;
-    int j;
-    int k;
-    int err;
-    int allInExtRange;        /* all values within external range? */
-    int allInIntRange;        /* all values within internal range? */
-    int nels;
-    int nslabs;
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
+    int i, k, err, nslabs, ncid, cdf_format;
+    int allInExtRange;  /* all values within external range? */
+    int allInIntRange;  /* all values within internal range? */
+    int nok = 0;        /* count of valid comparisons */
     int canConvert;     /* Both text or both numeric */
+    IntType j;
+    IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK], mid[MAX_RANK];
     double expect[MAX_NELS];
     $1 value[MAX_NELS];
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    err = GetVara($1)(BAD_ID, 0, NULL, NULL, value);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    err = GetVara($1)(ncid, BAD_VARID, NULL, NULL, value);
+    IF (err != NC_ENOTVAR)
+        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = GetVara($1)(BAD_ID, i, NULL, NULL, value);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
         }
-        err = ncmpi_get_vara_$1_all(BAD_ID, i, start, edge, value);
-        IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
-        err = ncmpi_get_vara_$1_all(ncid, BAD_VARID, start, edge, value);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = GetVara($1)(ncid, i, NULL, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) {
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = GetVara($1)(ncid, i, start, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                error("expecting NC_ECHAR, but got %s", nc_err_code_name(err));
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) {
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EEDGE)
+            EXPECT_ERR(NC_EEDGE, err)
+        ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = var_shape[i][j]; /* causes NC_EINVALCOORDS */
-            err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value);
-            IF (canConvert && err != NC_EINVALCOORDS)
-                error("bad index: err = %d", err);
+            err = GetVara($1)(ncid, i, start, edge, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                start[j] = 0;
+                continue;
+            }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
             start[j] = 0;
             edge[j] = var_shape[i][j] + 1; /* causes NC_EEDGE */
-            err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value);
-            IF (canConvert && err != NC_EEDGE)
-                error("bad edge: err = %d", err);
+            err = GetVara($1)(ncid, i, start, edge, value);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
             edge[j] = 1;
         }
-        /* Check non-scalars for correct error returned even when */
-        /* there is nothing to get (edge[j]==0) */
-        if (var_rank[i] > 0) {
-            for (j = 0; j < var_rank[i]; j++) {
-                edge[j] = 0;
-            }
-            err = ncmpi_get_vara_$1_all(BAD_ID, i, start, edge, value);
-            IF (err != NC_EBADID) 
-                error("bad ncid: err = %d", err);
-            err = ncmpi_get_vara_$1_all(ncid, BAD_VARID, start, edge, value);
-            IF (err != NC_ENOTVAR) 
-                error("bad var id: err = %d", err);
-            for (j = 0; j < var_rank[i]; j++) {
-                if (var_dimid[i][j] > 0) {                /* skip record dim */
-                    start[j] = var_shape[i][j];
-                    err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value);
-                    IF (canConvert && err != NC_EINVALCOORDS)
-                        error("bad start: err = %d", err);
-                    start[j] = 0;
-                }
-            }
-            err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value);
-            if (canConvert) {
-                IF (err != NC_NOERR) 
-                    error("%s", ncmpi_strerror(err));
-            } else {
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[*]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_rank[i] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = GetVara($1)(ncid, i, start, edge, value);
+            if (!canConvert) {
                 IF (err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
+                start[j] = 0;
+                continue;
             }
-            for (j = 0; j < var_rank[i]; j++) {
-                edge[j] = 1;
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            start[j] = var_shape[i][j]+1; /* should cause NC_EINVALCOORDS */
+            err = GetVara($1)(ncid, i, start, edge, value);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            start[j] = 0;
+        }
+
+        err = GetVara($1)(ncid, i, start, edge, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+        } else if (var_rank[i] == 0) {
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
             }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        } else {
+            IF (err != NC_NOERR)
+                EXPECT_ERR(NC_NOERR, err)
         }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* get 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -364,7 +501,7 @@ test_ncmpi_get_vara_$1(void)
         }
         /* bits of k determine whether to get lower or upper part of dim */
         for (k = 0; k < nslabs; k++) {
-            nels = 1;
+            IntType nels = 1;
             for (j = 0; j < var_rank[i]; j++) {
                 if ((k >> j) & 1) {
                     start[j] = 0;
@@ -377,39 +514,44 @@ test_ncmpi_get_vara_$1(void)
             }
             allInExtRange = allInIntRange = 1;
             for (j = 0; j < nels; j++) {
+                int d;
                 err = toMixedBase(j, var_rank[i], edge, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase 1");
+                IF (err != 0) error("error in toMixedBase");
                 for (d = 0; d < var_rank[i]; d++)
                     index[d] += start[d];
-                expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1));
-                if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) {
+                expect[j] = hash4(cdf_format, var_type[i], var_rank[i], index,
+                                  NCT_ITYPE($1));
+                if (inRange3(cdf_format, expect[j],var_type[i],NCT_ITYPE($1))) {
 		    IfCheckTextChar($1, var_type[i])
                         allInIntRange &= CheckRange($1,expect[j]);
-                } else {
+                } else
                     allInExtRange = 0;
-                }
             }
-            if (var_rank[i] == 0 && i%2)
-                err = ncmpi_get_vara_$1_all(ncid, i, NULL, NULL, value);
-            else
-                err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value);
+            err = GetVara($1)(ncid, i, start, edge, value);
             if (canConvert) {
                 if (allInExtRange) {
                     if (allInIntRange) {
                         IF (err != NC_NOERR)
-                            error("%s", ncmpi_strerror(err));
+                            EXPECT_ERR(NC_NOERR, err)
                     } else {
                         IF (err != NC_ERANGE)
-                            error("Range error: err = %d", err);
+                            EXPECT_ERR(NC_ERANGE, err)
                     }
                 } else {
                     IF (err != NC_NOERR && err != NC_ERANGE)
-                        error("OK or Range error: err = %d", err);
+                        EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
                 }
                 for (j = 0; j < nels; j++) {
                     if (CheckNumRange($1, expect[j], var_type[i])) {
-                        IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){
+                        ifelse(`$1', `uchar', `
+                        /* in put_vars(), API _put_vara_double() is used to
+                         * write the NC_BYTE variables to files. In this
+                         * case, NC_BYTE variables are treated as signed
+                         * for CDF-1 and 2 formats. Thus, we must skip the
+                         * equal test below for uchar.
+                         */
+                        if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
+                        IF (!equal((double)value[j],expect[j],var_type[i],NCT_ITYPE($1))){
                             error("value read not that expected");
                             if (verbose) {
                                 error("\n");
@@ -420,20 +562,19 @@ test_ncmpi_get_vara_$1(void)
                                 error("expect: %g, ", expect[j]);
                                 error("got: %g", (double) value[j]);
                             }
-                        } else {
-                            nok++;
                         }
+                        ELSE_NOK
                     }
                 }
             } else {
-                IF (nels > 0 && err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
             }
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
@@ -457,73 +598,174 @@ dnl
 define(`TEST_NC_GET_VARS',dnl
 `dnl
 int
-test_ncmpi_get_vars_$1(void)
+TestFunc(vars)_$1(VarArgs)
 {
-    int ncid;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err;
-    int allInExtRange;        /* all values within external range? */
-    int allInIntRange;        /* all values within internal range? */
-    int nels;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
+    int i, k, d, err, nslabs, ncid, cdf_format;
+    int allInExtRange;  /* all values within external range? */
+    int allInIntRange;  /* all values within internal range? */
+    PTRDType nstarts;   /* number of different starts */
+    int nok = 0;        /* count of valid comparisons */
     int canConvert;     /* Both text or both numeric */
+    IntType j, m, nels;
+    IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
+    IntType index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
+    IntType sstride[MAX_RANK];
+    PTRDType stride[MAX_RANK];
     double expect[MAX_NELS];
     $1 value[MAX_NELS];
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    err = GetVars($1)(BAD_ID, 0, NULL, NULL, NULL, value);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    err = GetVars($1)(ncid, BAD_VARID, NULL, NULL, NULL, value);
+    IF (err != NC_ENOTVAR)
+        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = GetVars($1)(BAD_ID, i, NULL, NULL, NULL, value);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
         }
-        err = ncmpi_get_vars_$1_all(BAD_ID, i, start, edge, stride, value);
-        IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
-        err = ncmpi_get_vars_$1_all(ncid, BAD_VARID, start, edge, stride, value);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = GetVars($1)(ncid, i, NULL, NULL, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) {
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = GetVars($1)(ncid, i, start, NULL, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                error("expecting NC_ECHAR, but got %s", nc_err_code_name(err));
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) {
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EEDGE)
+            EXPECT_ERR(NC_EEDGE, err)
+        ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = var_shape[i][j];
-            err = ncmpi_get_vars_$1_all(ncid, i, start, edge, stride, value);
+            err = GetVars($1)(ncid, i, start, edge, stride, value);
             if (!canConvert) {
                 IF (err != NC_ECHAR)
-                    error("conversion: err = %d", err);
-            } else {
-                IF (err != NC_EINVALCOORDS)
-                    error("bad index: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
+                start[j] = 0;
+                continue;
+            }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;
+            err = GetVars($1)(ncid, i, start, edge, stride, value);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            edge[j] = 1;
+            stride[j] = 0;
+            err = GetVars($1)(ncid, i, start, edge, stride, value);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            stride[j] = 1;
+        }
+
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = GetVars($1)(ncid, i, start, edge, stride, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 start[j] = 0;
-                edge[j] = var_shape[i][j] + 1;
-                err = ncmpi_get_vars_$1_all(ncid, i, start, edge, stride, value);
-                IF (err != NC_EEDGE)
-                    error("bad edge: err = %d", err);
-                edge[j] = 1;
-                stride[j] = 0;
-                err = ncmpi_get_vars_$1_all(ncid, i, start, edge, stride, value);
-                IF (err != NC_ESTRIDE)
-                    error("bad stride: err = %d", err);
-                stride[j] = 1;
+                continue;
+            }
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            start[j] = var_shape[i][j]+1;  /* should cause NC_EINVALCOORDS */
+            err = GetVars($1)(ncid, i, start, edge, stride, value);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            start[j] = 0;
+            stride[j] = 0;
+            err = GetVars($1)(ncid, i, start, edge, stride, value);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            stride[j] = 1;
+        }
+
+        err = GetVars($1)(ncid, i, start, edge, stride, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+        } else if (var_rank[i] == 0) {
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
             }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        } else {
+            IF (err != NC_NOERR)
+                EXPECT_ERR(NC_NOERR, err)
         }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* get 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -543,16 +785,16 @@ test_ncmpi_get_vars_$1(void)
                     start[j] = mid[j];
                     edge[j] = var_shape[i][j] - mid[j];
                 }
-                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                stride[j] = (PTRDType)sstride[j];
                 nstarts *= stride[j];
             }
             for (m = 0; m < nstarts; m++) {
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
+                IF (err != 0) error("error in toMixedBase");
                 nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
-                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    count[j] = 1 + (edge[j]-index[j]-1) / (IntType)stride[j];
                     nels *= count[j];
                     index[j] += start[j];
                 }
@@ -560,7 +802,7 @@ test_ncmpi_get_vars_$1(void)
 /* TODO
                 if ( roll(2) ) {
                     for (j = 0; j < var_rank[i]; j++) {
-                        index[j] += (count[j] - 1) * stride[j];
+                        index[j] += (count[j] - 1) * (IntType)stride[j];
                         stride[j] = -stride[j];
                     }
                 }
@@ -568,39 +810,42 @@ test_ncmpi_get_vars_$1(void)
                 allInExtRange = allInIntRange = 1;
                 for (j = 0; j < nels; j++) {
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase 1");
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
-                        index2[d] = index[d] + index2[d] * stride[d];
-                    expect[j] = hash4(var_type[i], var_rank[i], index2, 
-                        NCT_ITYPE($1));
-                    if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) {
+                        index2[d] = index[d] + index2[d] * (IntType)stride[d];
+                    expect[j] = hash4(cdf_format, var_type[i], var_rank[i],
+                                      index2, NCT_ITYPE($1));
+                    if (inRange3(cdf_format, expect[j],var_type[i],NCT_ITYPE($1))) {
 		        IfCheckTextChar($1, var_type[i])
                             allInIntRange &= CheckRange($1,expect[j]);
-                    } else {
+                    } else
                         allInExtRange = 0;
-                    }
                 }
-                if (var_rank[i] == 0 && i%2 )
-                    err = ncmpi_get_vars_$1_all(ncid, i, NULL, NULL, NULL, value);
-                else
-                    err = ncmpi_get_vars_$1_all(ncid, i, index, count, stride, value);
+                err = GetVars($1)(ncid, i, index, count, stride, value);
                 if (canConvert) {
                     if (allInExtRange) {
                         if (allInIntRange) {
                             IF (err != NC_NOERR)
-                                error("%s", ncmpi_strerror(err));
+                                EXPECT_ERR(NC_NOERR, err)
                         } else {
                             IF (err != NC_ERANGE)
-                                error("Range error: err = %d", err);
+                                EXPECT_ERR(NC_ERANGE, err)
                         }
                     } else {
                         IF (err != NC_NOERR && err != NC_ERANGE)
-                            error("OK or Range error: err = %d", err);
+                            EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
                     }
                     for (j = 0; j < nels; j++) {
                         if (CheckNumRange($1, expect[j], var_type[i])) {
-                            IF (!equal(value[j],expect[j],var_type[i], NCT_ITYPE($1))){
+                            ifelse(`$1', `uchar', `
+                            /* in put_vars(), API _put_vara_double() is used to
+                             * write the NC_BYTE variables to files. In this
+                             * case, NC_BYTE variables are treated as signed
+                             * for CDF-1 and 2 formats. Thus, we must skip the
+                             * equal test below for uchar.
+                             */
+                            if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
+                            IF (!equal((double)value[j],expect[j],var_type[i], NCT_ITYPE($1))){
                                 error("value read not that expected");
                                 if (verbose) {
                                     error("\n");
@@ -611,22 +856,21 @@ test_ncmpi_get_vars_$1(void)
                                     error("expect: %g, ", expect[j]);
                                     error("got: %g", (double) value[j]);
                                 }
-                            } else {
-                                nok++;
                             }
+                            ELSE_NOK
                         }
                     }
                 } else {
-                    IF (nels > 0 && err != NC_ECHAR)
-                        error("wrong type: err = %d", err);
+                    IF (err != NC_ECHAR)
+                        EXPECT_ERR(NC_ECHAR, err)
                 }
             }
         }
 
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
@@ -650,75 +894,174 @@ dnl
 define(`TEST_NC_GET_VARM',dnl
 `dnl
 int
-test_ncmpi_get_varm_$1(void)
+TestFunc(varm)_$1(VarArgs)
 {
-    int ncid;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err;
-    int allInExtRange;        /* all values within external range? */
-    int allInIntRange;        /* all values within internal range? */
-    int nels;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    MPI_Offset imap[MAX_RANK];
+    int i, k, d, err, nslabs, ncid, cdf_format;
+    int allInExtRange;  /* all values within external range? */
+    int allInIntRange;  /* all values within internal range? */
+    PTRDType nstarts;   /* number of different starts */
+    int nok = 0;        /* count of valid comparisons */
     int canConvert;     /* Both text or both numeric */
+    IntType j, m, nels;
+    IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
+    IntType index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
+    IntType sstride[MAX_RANK];
+    PTRDType stride[MAX_RANK], imap[MAX_RANK];
     double expect[MAX_NELS];
     $1 value[MAX_NELS];
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    err = GetVarm($1)(BAD_ID, 0, NULL, NULL, NULL, NULL, value);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    err = GetVarm($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, value);
+    IF (err != NC_ENOTVAR)
+        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = GetVars($1)(BAD_ID, i, NULL, NULL, NULL, value);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
             imap[j] = 1;
         }
-        err = ncmpi_get_varm_$1_all(BAD_ID, i, start, edge, stride, imap, value);
-        IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
-        err = ncmpi_get_varm_$1_all(ncid, BAD_VARID, start, edge, stride, imap, value);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = GetVarm($1)(ncid, i, NULL, NULL, NULL, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                error("expecting NC_ECHAR, but got %s", nc_err_code_name(err));
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) {
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = GetVarm($1)(ncid, i, start, NULL, NULL, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                error("expecting NC_ECHAR, but got %s", nc_err_code_name(err));
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) {
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EEDGE)
+            EXPECT_ERR(NC_EEDGE, err)
+        ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = var_shape[i][j];
-            err = ncmpi_get_varm_$1_all(ncid, i, start, edge, stride, imap, value);
+            err = GetVarm($1)(ncid, i, start, edge, stride, imap, value);
             if (!canConvert) {
                 IF (err != NC_ECHAR)
-                    error("conversion: err = %d", err);
-            } else {
-                IF (err != NC_EINVALCOORDS)
-                    error("bad index: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
+                continue;
+            }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;
+            err = GetVarm($1)(ncid, i, start, edge, stride, imap, value);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            edge[j] = 1;
+            stride[j] = 0;
+            err = GetVarm($1)(ncid, i, start, edge, stride, imap, value);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            stride[j] = 1;
+        }
+
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = GetVarm($1)(ncid, i, start, edge, stride, imap, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 start[j] = 0;
-                edge[j] = var_shape[i][j] + 1;
-                err = ncmpi_get_varm_$1_all(ncid, i, start, edge, stride, imap, value);
-                IF (err != NC_EEDGE)
-                    error("bad edge: err = %d", err);
-                edge[j] = 1;
-                stride[j] = 0;
-                err = ncmpi_get_varm_$1_all(ncid, i, start, edge, stride, imap, value);
-                IF (err != NC_ESTRIDE)
-                    error("bad stride: err = %d", err);
-                stride[j] = 1;
+                continue;
             }
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            start[j] = var_shape[i][j]+1;  /* should cause NC_EINVALCOORDS */
+            err = GetVarm($1)(ncid, i, start, edge, stride, imap, value);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            start[j] = 0;
+            stride[j] = 0;
+            err = GetVarm($1)(ncid, i, start, edge, stride, imap, value);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            stride[j] = 1;
         }
+
+        err = GetVarm($1)(ncid, i, start, edge, stride, imap, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+        } else if (var_rank[i] == 0) {
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        } else {
+            IF (err != NC_NOERR)
+                EXPECT_ERR(NC_NOERR, err)
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* get 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -738,16 +1081,16 @@ test_ncmpi_get_varm_$1(void)
                     start[j] = mid[j];
                     edge[j] = var_shape[i][j] - mid[j];
                 }
-                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                stride[j] = (PTRDType)sstride[j];
                 nstarts *= stride[j];
             }
             for (m = 0; m < nstarts; m++) {
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
+                IF (err != 0) error("error in toMixedBase");
                 nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
-                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    count[j] = 1 + (edge[j]-index[j]-1) / (IntType)stride[j];
                     nels *= count[j];
                     index[j] += start[j];
                 }
@@ -755,53 +1098,56 @@ test_ncmpi_get_varm_$1(void)
 /* TODO
                 if ( roll(2) ) {
                     for (j = 0; j < var_rank[i]; j++) {
-                        index[j] += (count[j] - 1) * stride[j];
+                        index[j] += (count[j] - 1) * (IntType)stride[j];
                         stride[j] = -stride[j];
                     }
                 }
  */
                 if (var_rank[i] > 0) {
-                    j = var_rank[i] - 1;
-                    imap[j] = 1;
-                    for (; j > 0; j--)
-                        imap[j-1] = imap[j] * count[j];
+                    int jj = var_rank[i] - 1;
+                    imap[jj] = 1;
+                    for (; jj > 0; jj--)
+                        imap[jj-1] = imap[jj] * (PTRDType)count[jj];
                 }
                 allInExtRange = allInIntRange = 1;
                 for (j = 0; j < nels; j++) {
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase 1");
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
-                        index2[d] = index[d] + index2[d] * stride[d];
-                    expect[j] = hash4(var_type[i], var_rank[i], index2,
-                        NCT_ITYPE($1));
-                    if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) {
+                        index2[d] = index[d] + index2[d] * (IntType)stride[d];
+                    expect[j] = hash4(cdf_format, var_type[i], var_rank[i],
+                                      index2, NCT_ITYPE($1));
+                    if (inRange3(cdf_format, expect[j],var_type[i],NCT_ITYPE($1))) {
 		        IfCheckTextChar($1, var_type[i])
                             allInIntRange &= CheckRange($1,expect[j]);
-                    } else {
+                    } else
                         allInExtRange = 0;
-                    }
                 }
-                if (var_rank[i] == 0 && i%2 )
-                    err = ncmpi_get_varm_$1_all(ncid,i,NULL,NULL,NULL,NULL,value);
-                else
-                    err = ncmpi_get_varm_$1_all(ncid,i,index,count,stride,imap,value);
+                err = GetVarm($1)(ncid,i,index,count,stride,imap,value);
                 if (canConvert) {
                     if (allInExtRange) {
                         if (allInIntRange) {
                             IF (err != NC_NOERR)
-                                error("%s", ncmpi_strerror(err));
+                                EXPECT_ERR(NC_NOERR, err)
                         } else {
                             IF (err != NC_ERANGE)
-                                error("Range error: err = %d", err);
+                                EXPECT_ERR(NC_ERANGE, err)
                         }
                     } else {
                         IF (err != NC_NOERR && err != NC_ERANGE)
-                            error("OK or Range error: err = %d", err);
+                            EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
                     }
                     for (j = 0; j < nels; j++) {
                         if (CheckNumRange($1, expect[j], var_type[i])) {
-                            IF (!equal(value[j],expect[j],var_type[i], NCT_ITYPE($1))){
+                            ifelse(`$1', `uchar', `
+                            /* in put_vars(), API _put_vara_double() is used to
+                             * write the NC_BYTE variables to files. In this
+                             * case, NC_BYTE variables are treated as signed
+                             * for CDF-1 and 2 formats. Thus, we must skip the
+                             * equal test below for uchar.
+                             */
+                            if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
+                            IF (!equal((double)value[j],expect[j],var_type[i], NCT_ITYPE($1))){
                                 error("value read not that expected");
                                 if (verbose) {
                                     error("\n");
@@ -812,21 +1158,20 @@ test_ncmpi_get_varm_$1(void)
                                     error("expect: %g, ", expect[j]);
                                     error("got: %g", (double) value[j]);
                                 }
-                            } else {
-                                nok++;
                             }
+                            ELSE_NOK
                         }
                     }
                 } else {
-                    IF (nels > 0 && err != NC_ECHAR)
-                        error("wrong type: err = %d", err);
+                    IF (err != NC_ECHAR)
+                        EXPECT_ERR(NC_ECHAR, err)
                 }
             }
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
@@ -850,13 +1195,10 @@ dnl
 define(`TEST_NC_GET_ATT',dnl
 `dnl
 int
-test_ncmpi_get_att_$1(void)
+TestFunc(att)_$1(AttVarArgs)
 {
-    int ncid;
-    int i;
-    int j;
-    MPI_Offset k;
-    int err;
+    int i, j, err, ncid, cdf_format;
+    IntType k;
     int allInExtRange;
     int allInIntRange;
     int canConvert;     /* Both text or both numeric */
@@ -864,64 +1206,91 @@ test_ncmpi_get_att_$1(void)
     double expect[MAX_NELS];
     $1 value[MAX_NELS];
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    err = GetAtt($1)(BAD_ID, 0, NULL, value);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    err = GetAtt($1)(ncid, BAD_VARID, NULL, value);
+    IF (err != NC_ENOTVAR)
+        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+    ELSE_NOK
 
     for (i = -1; i < numVars; i++) {
         for (j = 0; j < NATTS(i); j++) {
             canConvert = (ATT_TYPE(i,j) == NC_CHAR) CheckText($1);
-            err = ncmpi_get_att_$1(BAD_ID, i, ATT_NAME(i,j), value);
-            IF (err != NC_EBADID) 
-                error("bad ncid: err = %d", err);
-            err = ncmpi_get_att_$1(ncid, BAD_VARID, ATT_NAME(i,j), value);
-            IF (err != NC_ENOTVAR) 
-                error("bad var id: err = %d", err);
-            err = ncmpi_get_att_$1(ncid, i, "noSuch", value);
-            IF (err != NC_ENOTATT) 
-                error("Bad attribute name: err = %d", err);
+
+            err = GetAtt($1)(ncid, BAD_VARID, ATT_NAME(i,j), value);
+            IF (err != NC_ENOTVAR)
+                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+            ELSE_NOK
+
+            /* check if can detect a bad name */
+            err = GetAtt($1)(ncid, i, NULL, NULL);
+            IF (err != NC_EBADNAME)
+                error("expecting NC_EBADNAME but got %s", nc_err_code_name(err));
+            ELSE_NOK
+
+            err = GetAtt($1)(ncid, i, "noSuch", value);
+            IF (err != NC_ENOTATT)
+                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+
             allInExtRange = allInIntRange = 1;
             for (k = 0; k < ATT_LEN(i,j); k++) {
-                expect[k] = hash4(ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1));
-                if (inRange3(expect[k],ATT_TYPE(i,j),NCT_ITYPE($1))) {
+                expect[k] = hash4(cdf_format, ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1));
+                if (inRange3(cdf_format, expect[k],ATT_TYPE(i,j),NCT_ITYPE($1))) {
 		    /* netCDF specification make a special case for type
 		     * conversion between uchar and scahr: do not check for
 		     * range error. See
-		     * http://www.unidata.ucar.edu/software/netcdf/docs_rc/data_type.html#type_conversion
+		     * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
                      */
 		    IfCheckTextChar($1, ATT_TYPE(i,j))
-		    ifelse(`$1',`uchar', `if (ATT_TYPE(i,j) != NC_BYTE)')
+		    ifelse(`$1',`uchar', `if (cdf_format > NC_FORMAT_64BIT_OFFSET || (cdf_format < NC_FORMAT_CDF5 && ATT_TYPE(i,j) != NC_BYTE))')
                         allInIntRange &= CheckRange($1,expect[k]);
                 } else {
                     allInExtRange = 0;
                 }
             }
-            err = ncmpi_get_att_$1(ncid, i, ATT_NAME(i,j), value);
+            err = GetAtt($1)(ncid, i, ATT_NAME(i,j), value);
             if (canConvert || ATT_LEN(i,j) == 0) {
                 if (allInExtRange) {
                     if (allInIntRange) {
                         IF (err != NC_NOERR)
-                            error("%s", ncmpi_strerror(err));
+                            error("%s", APIFunc(strerror)(err));
                     } else {
                         IF (err != NC_ERANGE)
-                            error("Range error: err = %d", err);
+                            error("expecting NC_ERANGE but got %s", nc_err_code_name(err));
                     }
                 } else {
                     IF (err != NC_NOERR && err != NC_ERANGE)
-                        error("OK or Range error: err = %d", err);
+                        error("expecting NC_NOERR or NC_ERANGE but got %s", nc_err_code_name(err));
                 }
                 for (k = 0; k < ATT_LEN(i,j); k++) {
                     if (CheckNumRange($1, expect[k], ATT_TYPE(i,j))) {
-                        IF (!equal(value[k],expect[k],ATT_TYPE(i,j), NCT_ITYPE($1))){
+                        ifelse(`$1', `uchar', `
+                        /* in put_vars(), API _put_vara_double() is used to
+                         * write the NC_BYTE variables to files. In this
+                         * case, NC_BYTE variables are treated as signed
+                         * for CDF-1 and 2 formats. Thus, we must skip the
+                         * equal test below for uchar.
+                         */
+                        if (cdf_format < NC_FORMAT_CDF5 && ATT_TYPE(i,j) == NC_BYTE && expect[k] > schar_max) continue;')
+                        IF (!equal((double)value[k],expect[k],ATT_TYPE(i,j), NCT_ITYPE($1))){
                             error("value read not that expected");
                             if (verbose) {
                                 error("\n");
                                 error("varid: %d, ", i);
-                                error("att_name: %s, ", ATT_NAME(i,j));
                                 if (i == -1)
                                     error("var_type: GLOBAL, ");
                                 else
-                                    error("var_type: %s, ", s_nc_type(var_type[i]));
+                                    error("var_name: %s var_type: %s, ", var_name[i],s_nc_type(var_type[i]));
+                                error("att_name: %s, ", ATT_NAME(i,j));
                                 error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                                 error("element number: %d, ", k);
                                 error("expect: %g, ", expect[k]);
@@ -934,14 +1303,14 @@ test_ncmpi_get_att_$1(void)
                 }
             } else {
                 IF (err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                    error("wrong type: expecting NC_ECHAR but got %s", nc_err_code_name(err));
             }
         }
     }
 
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
diff --git a/test/nc_test/test_iget.m4 b/test/nc_test/test_iget.m4
index d54a30b..7f8aee4 100644
--- a/test/nc_test/test_iget.m4
+++ b/test/nc_test/test_iget.m4
@@ -8,9 +8,28 @@ dnl
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: test_iget.m4 2293 2016-01-06 03:43:04Z wkliao $ */
+/* $Id: test_iget.m4 2616 2016-11-14 09:19:14Z wkliao $ */
 
 
+define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl
+
+define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl
+define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl
+define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_iget_$1',`test_nc_iget_$1')')dnl
+define(`APIFunc',` ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl
+
+define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, &ncid)', `fi
+le_open($1, $2, &ncid)')')dnl
+
+define(`VarArgs',   `ifdef(`PNETCDF',`int numVars',`void')')dnl
+define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts,int numVars',`void')')dnl
+
+define(`iGetVar1',`ifdef(`PNETCDF',`ncmpi_iget_var1_$1',`nc_iget_var1_$1')')dnl
+define(`iGetVar', `ifdef(`PNETCDF',`ncmpi_iget_var_$1', `nc_iget_var_$1')')dnl
+define(`iGetVara',`ifdef(`PNETCDF',`ncmpi_iget_vara_$1',`nc_iget_vara_$1')')dnl
+define(`iGetVars',`ifdef(`PNETCDF',`ncmpi_iget_vars_$1',`nc_iget_vars_$1')')dnl
+define(`iGetVarm',`ifdef(`PNETCDF',`ncmpi_iget_varm_$1',`nc_iget_varm_$1')')dnl
+
 undefine(`index')dnl
 dnl dnl dnl
 dnl
@@ -35,82 +54,113 @@ define(`CheckRange',`ifelse(`$1',`text', `1', `($2 >= $1_min && $2 <= $1_max)')'
 define(`IfCheckTextChar', `ifelse(`$1',`text', `if ($2 != NC_CHAR)')')dnl
 define(`CheckNumRange',
        `ifelse(`$1',`text', `1',
-               `inRange3($2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
+               `inRange3(cdf_format, $2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
 
 #include "tests.h"
 
 int
-test_ncmpi_iget_var1(void)
+TestFunc(var1)(VarArgs)
 {
-    int i, j, err, ncid, nok = 0; /* count of valid comparisons */
-    MPI_Offset index[MAX_RANK];
-    double expect, value, buf[1];
-    int reqid, status;
+    int i, j, err, ncid, nok=0, reqid;
+    IntType index[MAX_RANK];
+    double expect, value[1];
     MPI_Datatype datatype;
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = APIFunc(iget_var1)(BAD_ID, 0, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = APIFunc(iget_var1)(ncid, BAD_VARID, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        for (j = 0; j < var_rank[i]; j++) index[j] = 0;
-        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
 
-        /* check if pnetcdf can detect a bad file ID */
-        err = ncmpi_iget_var1(BAD_ID, i, index, buf, 1, datatype, &reqid);
+        /* check if can detect a bad file ID */
+        err = APIFunc(iget_var1)(BAD_ID, i, NULL, value, 1, MPI_DATATYPE_NULL, NULL);
         IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
+            EXPECT_ERR(NC_EBADID, err)
         ELSE_NOK
-        err = ncmpi_iget_var1(ncid, BAD_VARID, index, buf, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+        datatype = nc_mpi_type(var_type[i]);
+
+ifdef(`PNETCDF',`dnl
+        err = APIFunc(iget_var1)(ncid, i, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        /* check if pnetcdf can detect out of boundary requests */
+')dnl
+
+        /* test NC_EINVALCOORDS */
         for (j = 0; j < var_rank[i]; j++) {
             index[j] = var_shape[i][j]; /* make an out-of-boundary starts[] */
-            err = ncmpi_iget_var1(ncid, i, index, buf, 1, datatype, &reqid);
+            err = APIFunc(iget_var1)(ncid, i, index, value, 1, datatype, &reqid);
             IF (err != NC_EINVALCOORDS)
-                error("bad index: err = %d", err);
+                EXPECT_ERR(NC_EINVALCOORDS, err)
             ELSE_NOK
             index[j] = 0;
         }
+        err = APIFunc(iget_var1)(ncid, i, index, value, 1, datatype, &reqid);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+        err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+
         /* check if the contents are supposed to be */
         for (j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR)
-                error("error in toMixedBase 1");
-
+            IF (err != 0) error("error in toMixedBase");
             /* when file is created the variable contents are generated by
              * hash functions */
             expect = hash(var_type[i], var_rank[i], index);
-            if (var_rank[i] == 0 && i%2 )
-                err = ncmpi_iget_var1(ncid, i, NULL, buf, 1, datatype, &reqid);
-            else
-                err = ncmpi_iget_var1(ncid, i, index, buf, 1, datatype, &reqid);
+            err = APIFunc(iget_var1)(ncid, i, index, value, 1, datatype, &reqid);
             IF (err != NC_NOERR)
-                error("ncmpi_iget_var: %s", ncmpi_strerror(err));
+                EXPECT_ERR(NC_NOERR, err)
             ELSE_NOK
-
-            err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
             IF (err != NC_NOERR)
-                error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+                EXPECT_ERR(NC_NOERR, err)
             ELSE_NOK
-
-            err = nc2dbl( var_type[i], buf, &value );
+            err = nc2dbl(var_type[i], value, value);
             IF (err)
                 error("error in nc2dbl");
             if (inRange(expect,var_type[i])) {
-                IF (!equal2(value,expect,var_type[i])) {
-                    error("expected: %G, got: %G", expect, value);
-                } else {
-                    nok++;
-                }   
+                ifelse(`$1', `uchar', `
+                /* in put_vars(), API _put_vara_double() is used to
+                 * write the NC_BYTE variables to files. In this
+                 * case, NC_BYTE variables are treated as signed
+                 * for CDF-1 and 2 formats. Thus, we must skip the
+                 * equal test below for uchar.
+                 */
+                if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect > schar_max) continue;')
+                IF (!equal2(value[0],expect,var_type[i])) {
+                    error("expected: %G, got: %G", expect, value[0]);
+                }
+                ELSE_NOK
             }
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 
@@ -119,97 +169,132 @@ dnl
 define(`TEST_NC_IGET_VAR1',dnl
 `dnl
 int
-test_ncmpi_iget_var1_$1(void)
+TestFunc(var1)_$1(VarArgs)
 {
-    int ncid;
-    int i;
-    int j;
-    int err;
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset index[MAX_RANK];
+    int i, err, ncid, cdf_format, reqid;
+    int nok = 0;        /* count of valid comparisons */
     int canConvert;     /* Both text or both numeric */
+    IntType j, index[MAX_RANK];
     double expect;
-    $1 value;
-    int reqid, status;
+    $1 value[1];
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = iGetVar1($1)(BAD_ID, 0, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = iGetVar1($1)(ncid, BAD_VARID, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
-        for (j = 0; j < var_rank[i]; j++)
-            index[j] = 0;
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
 
-        /* check if pnetcdf can detect a bad file ID */
-        err = ncmpi_iget_var1_$1(BAD_ID, i, index, &value, &reqid);
+        /* check if can detect a bad file ID */
+        err = iGetVar1($1)(BAD_ID, i, NULL, value, NULL);
         IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
+            EXPECT_ERR(NC_EBADID, err)
         ELSE_NOK
-        err = ncmpi_iget_var1_$1(ncid, BAD_VARID, index, &value, &reqid);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = iGetVar1($1)(ncid, i, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            index[0] = 0;
+            expect = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect, var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect)) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        /* check if pnetcdf can detect out of boundary requests */
+')dnl
+
+        /* test NC_EINVALCOORDS */
+        for (j = 0; j < var_rank[i]; j++) index[j] = 0;
+
         for (j = 0; j < var_rank[i]; j++) {
             index[j] = var_shape[i][j]; /* make an out-of-boundary starts[] */
-            err = ncmpi_iget_var1_$1(ncid, i, index, &value, &reqid);
+            err = iGetVar1($1)(ncid, i, index, value, &reqid);
             if (!canConvert) {
                 IF (err != NC_ECHAR)
-                    error("conversion: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
             } else IF (err != NC_EINVALCOORDS)
-                error("bad index: err = %d", err);
+                EXPECT_ERR(NC_EINVALCOORDS, err)
             ELSE_NOK
             index[j] = 0;
         }
+
         /* check if the contents are supposed to be */
         for (j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR)
-                error("error in toMixedBase 1");
-
+            IF (err != 0) error("error in toMixedBase");
             /* when file is created the variable contents are generated by
              * hash functions */
-            expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1) );
-
-            if (var_rank[i] == 0 && i%2 )
-                err = ncmpi_iget_var1_$1(ncid, i, NULL, &value, &reqid);
-            else
-                err = ncmpi_iget_var1_$1(ncid, i, index, &value, &reqid);
-            if (err == NC_NOERR)
-                ncmpi_wait_all(ncid, 1, &reqid, &status);
-
+            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
+                           NCT_ITYPE($1));
+            err = iGetVar1($1)(ncid, i, index, value, &reqid);
             if (canConvert) {
-                if (inRange3(expect,var_type[i], NCT_ITYPE($1))) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                if (inRange3(cdf_format, expect,var_type[i], NCT_ITYPE($1))) {
                     if (CheckRange($1, expect)) {
-                        IF (status != NC_NOERR) {
-                            error("%s", ncmpi_strerror(status));
+                        IF (err != NC_NOERR) {
+                            EXPECT_ERR(NC_NOERR, err)
                         } else {
-                            IF (!equal(value,expect,var_type[i],NCT_ITYPE($1)))
-                                error("expected: %G, got: %G", expect,
-                                    (double) value);
+                            ifelse(`$1', `uchar', `
+                            /* in put_vars(), API _put_vara_double() is used to
+                             * write the NC_BYTE variables to files. In this
+                             * case, NC_BYTE variables are treated as signed
+                             * for CDF-1 and 2 formats. Thus, we must skip the
+                             * equal test below for uchar.
+                             */
+                            if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect > schar_max) continue;')
+                            IF (!equal(value[0],expect,var_type[i],NCT_ITYPE($1)))
+                                error("expected: %G, got: %G", expect, (double)value[0]);
                             ELSE_NOK
                         }
                     } else {
-                        IF (status != NC_ERANGE)
-                            error("Range error: status = %d", status);
+                        IF (err != NC_ERANGE)
+                            EXPECT_ERR(NC_ERANGE, err)
                         ELSE_NOK
                     }
                 } else {
-                    IF (status != NC_NOERR && status != NC_ERANGE)
-                        error("OK or Range error: status = %d", status);
+                    IF (err != NC_NOERR && err != NC_ERANGE)
+                        EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
                     ELSE_NOK
                 }
             } else {
                 IF (err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
             }
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
@@ -228,69 +313,71 @@ TEST_NC_IGET_VAR1(longlong)
 TEST_NC_IGET_VAR1(ulonglong)
 
 int
-test_ncmpi_iget_var(void)
+TestFunc(var)(VarArgs)
 {
-    int ncid;
-    int i;
-    int j;
-    int err, num_err;
-    int nels;
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset index[MAX_RANK];
-    double expect[MAX_NELS];
-    double buf[MAX_NELS];
-    int reqid, status;
+    int i, err, ncid, nok=0, reqid;
+    IntType j, index[MAX_RANK];
     MPI_Datatype datatype;
+    double value[MAX_NELS], expect[MAX_NELS];
+
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = APIFunc(iget_var)(BAD_ID, 0, NULL, 0, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = APIFunc(iget_var)(ncid, BAD_VARID, NULL, 0, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
     for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
 
-        /* check if pnetcdf can detect a bad file ID */
-        err = ncmpi_iget_var(BAD_ID, i, buf, 1, datatype, &reqid);
+        /* check if can detect a bad file ID */
+        err = APIFunc(iget_var)(BAD_ID, i, NULL, 0, MPI_DATATYPE_NULL, NULL);
         IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
-        ELSE_NOK
-        /* check if pnetcdf can detect a bad variable ID */
-        err = ncmpi_iget_var(ncid, BAD_VARID, buf, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+            EXPECT_ERR(NC_EBADID, err)
         ELSE_NOK
 
+        datatype = nc_mpi_type(var_type[i]);
+
         /* check if the contents are supposed to be */
-        nels = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            nels *= var_shape[i][j];
-        }
-        for (j = 0; j < nels; j++) {
+        for (j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR)
-                error("error in toMixedBase 1");
+            IF (err != 0) error("error in toMixedBase");
             expect[j] = hash(var_type[i], var_rank[i], index);
         }
-        err = ncmpi_iget_var(ncid, i, buf, nels, datatype, &reqid);
+        err = APIFunc(iget_var)(ncid, i, value, var_nels[i], datatype, &reqid);
         IF (err != NC_NOERR)
-            error("ncmpi_iget_var: %s", ncmpi_strerror(err));
+            EXPECT_ERR(NC_NOERR, err)
         ELSE_NOK
-
-        err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+        err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
         IF (err != NC_NOERR)
-            error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+            EXPECT_ERR(NC_NOERR, err)
         ELSE_NOK
 
-        num_err = 0;
-        for (j = 0; j < nels; j++) {
+        for (j = 0; j < var_nels[i]; j++) {
             double got;
-            char *p = (char *) buf;
+            char *p = (char *) value;
             p += j * nctypelen(var_type[i]);
             if (inRange(expect[j],var_type[i])) {
                 err = nc2dbl(var_type[i], p, &got);
                 IF (err != NC_NOERR)
                     error("error in nc2dbl");
+                ifelse(`$1', `uchar', `
+                /* in put_vars(), API _put_vara_double() is used to
+                 * write the NC_BYTE variables to files. In this
+                 * case, NC_BYTE variables are treated as signed
+                 * for CDF-1 and 2 formats. Thus, we must skip the
+                 * equal test below for uchar.
+                 */
+                if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
                 IF (!equal2(got,expect[j],var_type[i])) {
                     error("value read not that expected");
                     if (verbose) {
@@ -301,15 +388,14 @@ test_ncmpi_iget_var(void)
                         error("expect: %g", expect[j]);
                         error("got: %g", got);
                     }
-                    num_err++;
                 }
+                ELSE_NOK
             }
-            if (num_err == 0) nok++;
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 
@@ -318,82 +404,89 @@ dnl
 define(`TEST_NC_IGET_VAR',dnl
 `dnl
 int
-test_ncmpi_iget_var_$1(void)
+TestFunc(var)_$1(VarArgs)
 {
-    int ncid;
-    int i;
-    int j;
-    int err, num_err;
-    int allInExtRange;        /* all values within external range? */
-    int allInIntRange;        /* all values within internal range? */
-    int nels;
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset index[MAX_RANK];
+    int i, err, ncid, cdf_format, reqid;
+    int allInExtRange;  /* all values within range of external data type */
+    int allInIntRange;  /* all values within range of internal data type */
+    int nok = 0;        /* count of valid comparisons */
     int canConvert;     /* Both text or both numeric */
+    IntType j, index[MAX_RANK];
     double expect[MAX_NELS];
     $1 value[MAX_NELS];
-    int reqid, status;
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = iGetVar($1)(BAD_ID, 0, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = iGetVar($1)(ncid, BAD_VARID, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
 
-        /* check if pnetcdf can detect a bad file ID */
-        err = ncmpi_iget_var_$1(BAD_ID, i, value, &reqid);
+        /* check if can detect a bad file ID */
+        err = iGetVar($1)(BAD_ID, i, value, NULL);
         IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
-        ELSE_NOK
-        /* check if pnetcdf can detect a bad variable ID */
-        err = ncmpi_iget_var_$1(ncid, BAD_VARID, value, &reqid);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+            EXPECT_ERR(NC_EBADID, err)
         ELSE_NOK
 
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         /* check if the contents are supposed to be */
-        nels = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            nels *= var_shape[i][j];
-        }
         allInExtRange = allInIntRange = 1;
-        for (j = 0; j < nels; j++) {
+        for (j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR)
-                error("error in toMixedBase 1");
-            expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1));
-            if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) {
+            IF (err != 0) error("error in toMixedBase");
+            expect[j] = hash4(cdf_format, var_type[i], var_rank[i], index,
+                              NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[j],var_type[i], NCT_ITYPE($1))) {
                 IfCheckTextChar($1, var_type[i])
                     allInIntRange &= CheckRange($1, expect[j]);
-            } else {
+            } else
                 allInExtRange = 0;
-            }
         }
-        err = ncmpi_iget_var_$1(ncid, i, value, &reqid);
-        if (err == NC_NOERR)
-            ncmpi_wait_all(ncid, 1, &reqid, &status);
-        ELSE_NOK
+        err = iGetVar($1)(ncid, i, value, &reqid);
         if (canConvert) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
             if (allInExtRange) {
                 if (allInIntRange) {
-                    IF (status != NC_NOERR)
-                        error("%s", ncmpi_strerror(status));
+                    IF (err != NC_NOERR)
+                        EXPECT_ERR(NC_NOERR, err)
                     ELSE_NOK
                 } else {
-                    IF (status != NC_ERANGE)
-                        error("Range error: status = %d", status);
+                    IF (err != NC_ERANGE)
+                        EXPECT_ERR(NC_ERANGE, err)
                     ELSE_NOK
                 }
             } else {
-                IF (status != NC_NOERR && status != NC_ERANGE)
-                    error("OK or Range error: status = %d", status);
+                IF (err != NC_NOERR && err != NC_ERANGE)
+                    EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
                 ELSE_NOK
             }
-            num_err = 0;
-            for (j = 0; j < nels; j++) {
+            for (j = 0; j < var_nels[i]; j++) {
                 if (CheckNumRange($1, expect[j], var_type[i])) {
+                    ifelse(`$1', `uchar', `
+                    /* in put_vars(), API _put_vara_double() is used to
+                     * write the NC_BYTE variables to files. In this
+                     * case, NC_BYTE variables are treated as signed
+                     * for CDF-1 and 2 formats. Thus, we must skip the
+                     * equal test below for uchar.
+                     */
+                    if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
                     IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){
                         error("value read not that expected");
                         if (verbose) {
@@ -404,20 +497,19 @@ test_ncmpi_iget_var_$1(void)
                             error("expect: %g", expect[j]);
                             error("got: %g", (double) value[j]);
                         }
-                        num_err++;
                     }
+                    ELSE_NOK
                 }
             }
-            if (num_err == 0) nok++;
         } else {
-            IF (nels > 0 && err != NC_ECHAR)
-                error("wrong type: err = %d", err);
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
             ELSE_NOK
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
@@ -437,78 +529,117 @@ TEST_NC_IGET_VAR(ulonglong)
 
 
 int
-test_ncmpi_iget_vara(void)
+TestFunc(vara)(VarArgs)
 {
-    int ncid, d, i, j, k, err, num_err, nels, nslabs;
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
+    int i, j, k, err, ncid, nok=0, nslabs, reqid;
+    double value[MAX_NELS], expect[MAX_NELS];
+    IntType start[MAX_RANK], edge[MAX_RANK], mid[MAX_RANK], index[MAX_RANK];
     MPI_Datatype datatype;
-    double buf[MAX_NELS];
-    double expect[MAX_NELS];
-    int reqid, status;
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = APIFunc(iget_vara)(BAD_ID, 0, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = APIFunc(iget_vara)(ncid, BAD_VARID, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
     for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = APIFunc(iget_vara)(BAD_ID, i, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        datatype = nc_mpi_type(var_type[i]);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
         }
-        err = ncmpi_iget_vara(BAD_ID, i, start, edge, buf, 1, datatype, &reqid);
-        IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        err = APIFunc(iget_vara)(ncid, i, NULL, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        err = ncmpi_iget_vara(ncid, BAD_VARID, start, edge, buf, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+        err = APIFunc(iget_vara)(ncid, i, start, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE)
+            EXPECT_ERR(NC_EEDGE, err)
         ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS, first when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            start[j] = var_shape[i][j];  /* out of boundary check */
-            err = ncmpi_iget_vara(ncid, i, start, edge, buf, 1, datatype, &reqid);
+            start[j] = var_shape[i][j];
+            err = APIFunc(iget_vara)(ncid, i, start, edge, value, 1, datatype, &reqid);
             IF (err != NC_EINVALCOORDS)
-                error("bad index: err = %d", err);
+                EXPECT_ERR(NC_EINVALCOORDS, err)
             ELSE_NOK
             start[j] = 0;
             edge[j] = var_shape[i][j] + 1;  /* edge error check */
-            err = ncmpi_iget_vara(ncid, i, start, edge, buf, 1, datatype, &reqid);
+            err = APIFunc(iget_vara)(ncid, i, start, edge, value, 1, datatype, &reqid);
             IF (err != NC_EEDGE)
-                error("bad index/edge: err = %d", err);
+                EXPECT_ERR(NC_EEDGE, err)
             ELSE_NOK
             edge[j] = 1;
         }
-        /* Check non-scalars for correct error returned even when */
-        /* there is nothing to get (edge[j]==0) */
-        if (var_rank[i] > 0) {
-            for (j = 0; j < var_rank[i]; j++)
-                edge[j] = 0;
-            err = ncmpi_iget_vara(BAD_ID, i, start, edge, buf, 1, datatype, &reqid);
-            IF (err != NC_EBADID) 
-                error("bad ncid: err = %d", err);
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = APIFunc(iget_vara)(ncid, i, start, edge, value, 0, datatype, &reqid);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
             ELSE_NOK
-            err = ncmpi_iget_vara(ncid, BAD_VARID, start, edge, buf, 1, datatype, &reqid);
-            IF (err != NC_ENOTVAR) 
-                error("bad var id: err = %d", err);
+            start[j] = var_shape[i][j]+1;  /* out of boundary check */
+            err = APIFunc(iget_vara)(ncid, i, start, edge, value, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
             ELSE_NOK
-            for (j = 0; j < var_rank[i]; j++) {
-                if (var_dimid[i][j] > 0) {                /* skip record dim */
-                    start[j] = var_shape[i][j];     /* out of boundary check */
-                    err = ncmpi_iget_vara(ncid, i, start, edge, buf, 1, datatype, &reqid);
-                    IF (err != NC_EINVALCOORDS)
-                        error("bad start: err = %d", err);
-                    ELSE_NOK
-                    start[j] = 0;
-                }
-            }
-            for (j = 0; j < var_rank[i]; j++)
-                edge[j] = 1;
+            start[j] = 0;
         }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
+        err = APIFunc(iget_vara)(ncid, i, start, edge, value, 1, datatype, &reqid);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+        err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+
         /* Choose a random point dividing each dim into 2 parts */
         /* get 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -518,7 +649,7 @@ test_ncmpi_iget_vara(void)
         }
         /* bits of k determine whether to get lower or upper part of dim */
         for (k = 0; k < nslabs; k++) {
-            nels = 1;
+            IntType nels = 1;
             for (j = 0; j < var_rank[i]; j++) {
                 if ((k >> j) & 1) {
                     start[j] = 0;
@@ -530,35 +661,38 @@ test_ncmpi_iget_vara(void)
                 nels *= edge[j];
             }
             for (j = 0; j < nels; j++) {
+                int d;
                 err = toMixedBase(j, var_rank[i], edge, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase 1");
+                IF (err != 0) error("error in toMixedBase");
                 for (d = 0; d < var_rank[i]; d++)
                     index[d] += start[d];
                 expect[j] = hash(var_type[i], var_rank[i], index);
             }
-            if (var_rank[i] == 0 && i%2)
-                err = ncmpi_iget_vara(ncid, i, NULL, NULL, buf, 1, datatype, &reqid);
-            else
-                err = ncmpi_iget_vara(ncid, i, start, edge, buf, nels, datatype, &reqid);
+            err = APIFunc(iget_vara)(ncid, i, start, edge, value, nels, datatype, &reqid);
             IF (err != NC_NOERR)
-                error("ncmpi_iget_vara %s", ncmpi_strerror(err));
+                EXPECT_ERR(NC_NOERR, err)
             ELSE_NOK
-
-            err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
             IF (err != NC_NOERR)
-                error("ncmpi_wait_all %s", ncmpi_strerror(err));
+                EXPECT_ERR(NC_NOERR, err)
             ELSE_NOK
 
-            num_err = 0;
             for (j = 0; j < nels; j++) {
                 double got;
-                char *p = (char *) buf;
+                char *p = (char *) value;
                 p += j * nctypelen(var_type[i]);
                 if (inRange(expect[j],var_type[i])) {
                     err = nc2dbl(var_type[i], p, &got);
                     IF (err != NC_NOERR)
                         error("error in nc2dbl");
+                    ifelse(`$1', `uchar', `
+                    /* in put_vars(), API _put_vara_double() is used to
+                     * write the NC_BYTE variables to files. In this
+                     * case, NC_BYTE variables are treated as signed
+                     * for CDF-1 and 2 formats. Thus, we must skip the
+                     * equal test below for uchar.
+                     */
+                    if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
                     IF (!equal2(got,expect[j],var_type[i])) {
                         error("value read not that expected");
                         if (verbose) {
@@ -569,16 +703,15 @@ test_ncmpi_iget_vara(void)
                             error("expect: %g", expect[j]);
                             error("got: %g", got);
                         }
-                        num_err++;
                     }
+                    ELSE_NOK
                 }
-                if (num_err == 0) nok++;
             }
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 
@@ -587,102 +720,170 @@ dnl
 define(`TEST_NC_IGET_VARA',dnl
 `dnl
 int
-test_ncmpi_iget_vara_$1(void)
+TestFunc(vara)_$1(VarArgs)
 {
-    int ncid;
-    int d;
-    int i;
-    int j;
-    int k;
-    int err, num_err;
-    int allInExtRange;        /* all values within external range? */
-    int allInIntRange;        /* all values within internal range? */
-    int nels;
-    int nslabs;
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
+    int i, k, err, nslabs, ncid, cdf_format, reqid;
+    int allInExtRange;  /* all values within external range? */
+    int allInIntRange;  /* all values within internal range? */
+    int nok = 0;        /* count of valid comparisons */
     int canConvert;     /* Both text or both numeric */
+    IntType j;
+    IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK], mid[MAX_RANK];
     double expect[MAX_NELS];
     $1 value[MAX_NELS];
-    int reqid, status;
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = iGetVara($1)(BAD_ID, 0, NULL, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = iGetVara($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = iGetVara($1)(BAD_ID, i, NULL, NULL, value, &reqid);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
         }
-        err = ncmpi_iget_vara_$1(BAD_ID, i, start, edge, value, &reqid);
-        IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        err = iGetVara($1)(ncid, i, NULL, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EINVALCOORDS)
+            EXPECT_ERR(NC_EINVALCOORDS, err)
         ELSE_NOK
-        err = ncmpi_iget_vara_$1(ncid, BAD_VARID, start, edge, value, &reqid);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+        err = iGetVara($1)(ncid, i, start, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EEDGE)
+            EXPECT_ERR(NC_EEDGE, err)
         ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS and NC_EEDGE, first when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            start[j] = var_shape[i][j];  /* out of boundary check */
-            err = ncmpi_iget_vara_$1(ncid, i, start, edge, value, &reqid);
-            IF (canConvert && err != NC_EINVALCOORDS)
-                error("bad index: err = %d", err);
+            start[j] = var_shape[i][j];
+            err = iGetVara($1)(ncid, i, start, edge, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
+                start[j] = 0;
+                continue;
+            }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
             ELSE_NOK
-            if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
             start[j] = 0;
             edge[j] = var_shape[i][j] + 1;  /* edge error check */
-            err = ncmpi_iget_vara_$1(ncid, i, start, edge, value, &reqid);
-            IF (canConvert && err != NC_EEDGE)
-                error("bad index/edge: err = %d", err);
+            err = iGetVara($1)(ncid, i, start, edge, value, &reqid);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
             ELSE_NOK
-            if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
             edge[j] = 1;
         }
-        /* Check non-scalars for correct error returned even when */
-        /* there is nothing to get (edge[j]==0) */
-        if (var_rank[i] > 0) {
-            for (j = 0; j < var_rank[i]; j++) {
-                edge[j] = 0;
-            }
-            err = ncmpi_iget_vara_$1(BAD_ID, i, start, edge, value, &reqid);
-            IF (err != NC_EBADID) 
-                error("bad ncid: err = %d", err);
-            ELSE_NOK
-            err = ncmpi_iget_vara_$1(ncid, BAD_VARID, start, edge, value, &reqid);
-            IF (err != NC_ENOTVAR) 
-                error("bad var id: err = %d", err);
-            ELSE_NOK
-            for (j = 0; j < var_rank[i]; j++) {
-                if (var_dimid[i][j] > 0) {                /* skip record dim */
-                    start[j] = var_shape[i][j];     /* out of boundary check */
-                    err = ncmpi_iget_vara_$1(ncid, i, start, edge, value, &reqid);
-                    IF (canConvert && err != NC_EINVALCOORDS)
-                        error("bad start: err = %d", err);
-                    ELSE_NOK
-                    if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
-                    start[j] = 0;
-                }
-            }
-            err = ncmpi_iget_vara_$1(ncid, i, start, edge, value, &reqid);
-            if (canConvert) {
-                IF (err != NC_NOERR)
-                    error("Error: ncmpi_iget_vara_$1 %s",ncmpi_strerror(err));
-            } else {
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_rank[i] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = iGetVara($1)(ncid, i, start, edge, value, &reqid);
+            if (!canConvert) {
                 IF (err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
+                start[j] = 0;
+                continue;
             }
-            if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
-            for (j = 0; j < var_rank[i]; j++) {
-                edge[j] = 1;
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = iGetVara($1)(ncid, i, start, edge, value, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        err = iGetVara($1)(ncid, i, start, edge, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+        } else if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
             }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        } else {
+            IF (err != NC_NOERR)
+                EXPECT_ERR(NC_NOERR, err)
         }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* get 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -692,7 +893,7 @@ test_ncmpi_iget_vara_$1(void)
         }
         /* bits of k determine whether to get lower or upper part of dim */
         for (k = 0; k < nslabs; k++) {
-            nels = 1;
+            IntType nels = 1;
             for (j = 0; j < var_rank[i]; j++) {
                 if ((k >> j) & 1) {
                     start[j] = 0;
@@ -705,44 +906,49 @@ test_ncmpi_iget_vara_$1(void)
             }
             allInExtRange = allInIntRange = 1;
             for (j = 0; j < nels; j++) {
+                int d;
                 err = toMixedBase(j, var_rank[i], edge, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase 1");
+                IF (err != 0) error("error in toMixedBase");
                 for (d = 0; d < var_rank[i]; d++)
                     index[d] += start[d];
-                expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1));
-                if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) {
+                expect[j] = hash4(cdf_format, var_type[i], var_rank[i], index,
+                                  NCT_ITYPE($1));
+                if (inRange3(cdf_format, expect[j],var_type[i], NCT_ITYPE($1))) {
                     IfCheckTextChar($1, var_type[i])
                         allInIntRange &= CheckRange($1, expect[j]);
                 } else {
                     allInExtRange = 0;
                 }
             }
-            if (var_rank[i] == 0 && i%2)
-                err = ncmpi_iget_vara_$1(ncid, i, NULL, NULL, value, &reqid);
-            else
-                err = ncmpi_iget_vara_$1(ncid, i, start, edge, value, &reqid);
-            if (err == NC_NOERR)
-                ncmpi_wait_all(ncid, 1, &reqid, &status);
+            err = iGetVara($1)(ncid, i, start, edge, value, &reqid);
             if (canConvert) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
                 if (allInExtRange) {
                     if (allInIntRange) {
-                        IF (status != NC_NOERR)
-                            error("%s", ncmpi_strerror(status));
+                        IF (err != NC_NOERR)
+                            EXPECT_ERR(NC_NOERR, err)
                         ELSE_NOK
                     } else {
-                        IF (status != NC_ERANGE)
-                            error("Range error: status = %d", status);
+                        IF (err != NC_ERANGE)
+                            EXPECT_ERR(NC_ERANGE, err)
                         ELSE_NOK
                     }
                 } else {
-                    IF (status != NC_NOERR && status != NC_ERANGE)
-                        error("OK or Range error: status = %d", status);
+                    IF (err != NC_NOERR && err != NC_ERANGE)
+                        EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
                     ELSE_NOK
                 }
-                num_err = 0;
                 for (j = 0; j < nels; j++) {
                     if (CheckNumRange($1, expect[j], var_type[i])) {
+                        ifelse(`$1', `uchar', `
+                        /* in put_vars(), API _put_vara_double() is used to
+                         * write the NC_BYTE variables to files. In this
+                         * case, NC_BYTE variables are treated as signed
+                         * for CDF-1 and 2 formats. Thus, we must skip the
+                         * equal test below for uchar.
+                         */
+                        if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
                         IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){
                             error("value read not that expected");
                             if (verbose) {
@@ -753,21 +959,20 @@ test_ncmpi_iget_vara_$1(void)
                                 error("expect: %g", expect[j]);
                                 error("got: %g", (double) value[j]);
                             }
-                            num_err++;
                         }
+                        ELSE_NOK
                     }
                 }
-                if (num_err == 0) nok++;
             } else {
-                IF (nels > 0 && err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
             }
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
@@ -786,73 +991,127 @@ TEST_NC_IGET_VARA(longlong)
 TEST_NC_IGET_VARA(ulonglong)
 
 int
-test_ncmpi_iget_vars(void)
+TestFunc(vars)(VarArgs)
 {
-    int ncid;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err, num_err;
-    int nels;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    double buf[MAX_NELS];
-    double expect[MAX_NELS];
-    int reqid, status;
+    int i, j, k, err, ncid, nok=0, nslabs, reqid;
+    double value[MAX_NELS], expect[MAX_NELS];
+    IntType m, start[MAX_RANK], index[MAX_RANK], index2[MAX_RANK];
+    IntType count[MAX_RANK], edge[MAX_RANK], mid[MAX_RANK], sstride[MAX_RANK];
+    PTRDType nstarts;   /* number of different starts */
+    PTRDType stride[MAX_RANK];
     MPI_Datatype datatype;
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = APIFunc(iget_vars)(BAD_ID, 0, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = APIFunc(iget_vars)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
     for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = APIFunc(iget_vars)(BAD_ID, i, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        datatype = nc_mpi_type(var_type[i]);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
         }
-        err = ncmpi_iget_vars(BAD_ID, i, start, edge, stride, buf, 1, datatype, &reqid);
-        IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        err = APIFunc(iget_vars)(ncid, i, NULL, NULL, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        err = ncmpi_iget_vars(ncid, BAD_VARID, start, edge, stride, buf, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+        err = APIFunc(iget_vars)(ncid, i, start, NULL, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE)
+            EXPECT_ERR(NC_EEDGE, err)
         ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS, first when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            start[j] = var_shape[i][j];    /* out of boundary check */
-            err = ncmpi_iget_vars(ncid, i, start, edge, stride, buf, 1, datatype, &reqid);
+            start[j] = var_shape[i][j];
+            err = APIFunc(iget_vars)(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
             IF (err != NC_EINVALCOORDS)
-                error("bad index: err = %d", err);
+                EXPECT_ERR(NC_EINVALCOORDS, err)
             ELSE_NOK
-
             start[j] = 0;
             edge[j] = var_shape[i][j] + 1;  /* edge error check */
-            err = ncmpi_iget_vars(ncid, i, start, edge, stride, buf, 1, datatype, &reqid);
+            err = APIFunc(iget_vars)(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
             IF (err != NC_EEDGE)
-                error("bad edge: err = %d", err);
+                EXPECT_ERR(NC_EEDGE, err)
             ELSE_NOK
             edge[j] = 1;
             stride[j] = 0;
-            err = ncmpi_iget_vars(ncid, i, start, edge, stride, buf, 1, datatype, &reqid);
+            err = APIFunc(iget_vars)(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
             IF (err != NC_ESTRIDE)
-                error("bad stride: err = %d", err);
+                EXPECT_ERR(NC_ESTRIDE, err)
             ELSE_NOK
             stride[j] = 1;
         }
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = APIFunc(iget_vars)(ncid, i, start, edge, stride, value, 0, datatype, &reqid);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1;  /* out of boundary check */
+            err = APIFunc(iget_vars)(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
+        err = APIFunc(iget_vars)(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+        err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+
         /* Choose a random point dividing each dim into 2 parts */
         /* get 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -877,10 +1136,8 @@ test_ncmpi_iget_vars(void)
             }
             for (m = 0; m < nstarts; m++) {
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
-                ELSE_NOK
-                nels = 1;
+                IF (err != 0) error("error in toMixedBase");
+                IntType nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
                     count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
                     nels *= count[j];
@@ -896,36 +1153,38 @@ test_ncmpi_iget_vars(void)
                 }
 */
                 for (j = 0; j < nels; j++) {
+                    int d;
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase 1");
-                    ELSE_NOK
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
                         index2[d] = index[d] + index2[d] * stride[d];
                     expect[j] = hash(var_type[i], var_rank[i], index2);
                 }
-                if (var_rank[i] == 0 && i%2 )
-                    err = ncmpi_iget_vars(ncid, i, NULL, NULL, NULL, buf, 1, datatype, &reqid);
-                else
-                    err = ncmpi_iget_vars(ncid, i, index, count, stride, buf, nels, datatype, &reqid);
+                err = APIFunc(iget_vars)(ncid, i, index, count, stride, value, nels, datatype, &reqid);
                 IF (err != NC_NOERR)
-                    error("%s", ncmpi_strerror(err));
+                    EXPECT_ERR(NC_NOERR, err)
                 ELSE_NOK
-
-                err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
                 IF (err != NC_NOERR)
-                    error("%s", ncmpi_strerror(err));
+                    EXPECT_ERR(NC_NOERR, err)
                 ELSE_NOK
 
-                num_err = 0;
                 for (j = 0; j < nels; j++) {
                     double got;
-                    char *p = (char *) buf;
+                    char *p = (char *) value;
                     p += j * nctypelen(var_type[i]);
                     if (inRange(expect[j],var_type[i])) {
                         err = nc2dbl(var_type[i], p, &got);
                         IF (err != NC_NOERR)
                             error("error in nc2dbl");
+                        ifelse(`$1', `uchar', `
+                        /* in put_vars(), API _put_vara_double() is used to
+                         * write the NC_BYTE variables to files. In this
+                         * case, NC_BYTE variables are treated as signed
+                         * for CDF-1 and 2 formats. Thus, we must skip the
+                         * equal test below for uchar.
+                         */
+                        if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
                         IF (!equal2(got,expect[j],var_type[i])) {
                             error("value read not that expected");
                             if (verbose) {
@@ -936,18 +1195,16 @@ test_ncmpi_iget_vars(void)
                                 error("expect: %g, ", expect[j]);
                                 error("got: %g", got);
                             }
-                            num_err++;
                         }
+                        ELSE_NOK
                     }
                 }
-                if (num_err == 0) nok++;
             }
         }
-
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 
@@ -956,80 +1213,181 @@ dnl
 define(`TEST_NC_IGET_VARS',dnl
 `dnl
 int
-test_ncmpi_iget_vars_$1(void)
+TestFunc(vars)_$1(VarArgs)
 {
-    int ncid;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err, num_err;
-    int allInExtRange;        /* all values within external range? */
-    int allInIntRange;        /* all values within internal range? */
-    int nels;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
+    int i, k, err, nslabs, ncid, cdf_format, reqid;
+    int allInExtRange;  /* all values within external range? */
+    int allInIntRange;  /* all values within internal range? */
+    int nok = 0;        /* count of valid comparisons */
     int canConvert;     /* Both text or both numeric */
+    IntType j, m;
+    IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
+    IntType index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
+    IntType sstride[MAX_RANK];
+    PTRDType nstarts;   /* number of different starts */
+    PTRDType stride[MAX_RANK];
     double expect[MAX_NELS];
     $1 value[MAX_NELS];
-    int reqid, status;
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = iGetVars($1)(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = iGetVars($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = iGetVars($1)(BAD_ID, i, NULL, NULL, NULL, value, &reqid);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
         }
-        err = ncmpi_iget_vars_$1(BAD_ID, i, start, edge, stride, value, &reqid);
-        IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        err = iGetVars($1)(ncid, i, NULL, NULL, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EINVALCOORDS)
+            EXPECT_ERR(NC_EINVALCOORDS, err)
         ELSE_NOK
-        err = ncmpi_iget_vars_$1(ncid, BAD_VARID, start, edge, stride, value, &reqid);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+        err = iGetVars($1)(ncid, i, start, NULL, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EEDGE)
+            EXPECT_ERR(NC_EEDGE, err)
         ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS, NC_EEDGE and NC_ESTRIDE, first when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            start[j] = var_shape[i][j];    /* out of boundary check */
-            err = ncmpi_iget_vars_$1(ncid, i, start, edge, stride, value, &reqid);
+            start[j] = var_shape[i][j];
+            err = iGetVars($1)(ncid, i, start, edge, stride, value, &reqid);
             if (!canConvert) {
                 IF (err != NC_ECHAR)
-                    error("conversion: err = %d", err);
-            } else {
-                IF (err != NC_EINVALCOORDS)
-                    error("bad index: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
-
                 start[j] = 0;
-                edge[j] = var_shape[i][j] + 1;  /* edge error check */
-                err = ncmpi_iget_vars_$1(ncid, i, start, edge, stride, value, &reqid);
-                IF (err != NC_EEDGE)
-                    error("bad edge: err = %d", err);
-                ELSE_NOK
-                edge[j] = 1;
-                stride[j] = 0;
-                err = ncmpi_iget_vars_$1(ncid, i, start, edge, stride, value, &reqid);
-                IF (err != NC_ESTRIDE)
-                    error("bad stride: err = %d", err);
+                continue;
+            }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = iGetVars($1)(ncid, i, start, edge, stride, value, &reqid);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;
+            err = iGetVars($1)(ncid, i, start, edge, stride, value, &reqid);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
+        }
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_rank[i] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = iGetVars($1)(ncid, i, start, edge, stride, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
-                stride[j] = 1;
+                start[j] = 0;
+                continue;
+            }
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = iGetVars($1)(ncid, i, start, edge, stride, value, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        err = iGetVars($1)(ncid, i, start, edge, stride, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+        } else if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
             }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        } else {
+            IF (err != NC_NOERR)
+                EXPECT_ERR(NC_NOERR, err)
         }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* get 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -1054,10 +1412,8 @@ test_ncmpi_iget_vars_$1(void)
             }
             for (m = 0; m < nstarts; m++) {
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
-                ELSE_NOK
-                nels = 1;
+                IF (err != 0) error("error in toMixedBase");
+                IntType nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
                     count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
                     nels *= count[j];
@@ -1074,46 +1430,49 @@ test_ncmpi_iget_vars_$1(void)
 */
                 allInExtRange = allInIntRange = 1;
                 for (j = 0; j < nels; j++) {
+                    int d;
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase 1");
-                    ELSE_NOK
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
                         index2[d] = index[d] + index2[d] * stride[d];
-                    expect[j] = hash4(var_type[i], var_rank[i], index2, 
-                        NCT_ITYPE($1));
-                    if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) {
+                    expect[j] = hash4(cdf_format, var_type[i], var_rank[i],
+                                      index2, NCT_ITYPE($1));
+                    if (inRange3(cdf_format, expect[j],var_type[i],NCT_ITYPE($1))) {
                         IfCheckTextChar($1, var_type[i])
                             allInIntRange &= CheckRange($1, expect[j]);
                     } else {
                         allInExtRange = 0;
                     }
                 }
-                if (var_rank[i] == 0 && i%2 )
-                    err = ncmpi_iget_vars_$1(ncid, i, NULL, NULL, NULL, value, &reqid);
-                else
-                    err = ncmpi_iget_vars_$1(ncid, i, index, count, stride, value, &reqid);
-                if (err == NC_NOERR)
-                    ncmpi_wait_all(ncid, 1, &reqid, &status);
+                err = iGetVars($1)(ncid, i, index, count, stride, value, &reqid);
                 if (canConvert) {
+                    IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+                    err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
                     if (allInExtRange) {
                         if (allInIntRange) {
-                            IF (status != NC_NOERR)
-                                error("%s", ncmpi_strerror(status));
+                            IF (err != NC_NOERR)
+                                EXPECT_ERR(NC_NOERR, err)
                             ELSE_NOK
                         } else {
-                            IF (status != NC_ERANGE)
-                                error("Range error: status = %d", status);
+                            IF (err != NC_ERANGE)
+                                EXPECT_ERR(NC_ERANGE, err)
                             ELSE_NOK
                         }
                     } else {
-                        IF (status != NC_NOERR && status != NC_ERANGE)
-                            error("OK or Range error: status = %d", status);
+                        IF (err != NC_NOERR && err != NC_ERANGE)
+                            EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
                         ELSE_NOK
                     }
-                    num_err = 0;
                     for (j = 0; j < nels; j++) {
                         if (CheckNumRange($1, expect[j], var_type[i])) {
+                            ifelse(`$1', `uchar', `
+                            /* in put_vars(), API _put_vara_double() is used to
+                             * write the NC_BYTE variables to files. In this
+                             * case, NC_BYTE variables are treated as signed
+                             * for CDF-1 and 2 formats. Thus, we must skip the
+                             * equal test below for uchar.
+                             */
+                            if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
                             IF (!equal(value[j],expect[j],var_type[i], NCT_ITYPE($1))){
                                 error("value read not that expected");
                                 if (verbose) {
@@ -1124,23 +1483,21 @@ test_ncmpi_iget_vars_$1(void)
                                     error("expect: %g, ", expect[j]);
                                     error("got: %g", (double) value[j]);
                                 }
-                                num_err++;
                             }
+                            ELSE_NOK
                         }
                     }
-                    if (num_err == 0) nok++;
                 } else {
-                    IF (nels > 0 && err != NC_ECHAR)
-                        error("wrong type: err = %d", err);
+                    IF (err != NC_ECHAR)
+                        EXPECT_ERR(NC_ECHAR, err)
                     ELSE_NOK
                 }
             }
         }
-
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
@@ -1159,74 +1516,128 @@ TEST_NC_IGET_VARS(longlong)
 TEST_NC_IGET_VARS(ulonglong)
 
 int
-test_ncmpi_iget_varm(void)
+TestFunc(varm)(VarArgs)
 {
-    int ncid;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err, num_err;
-    int nels;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    MPI_Offset imap[MAX_RANK];
-    double buf[MAX_NELS], expect[MAX_NELS];
-    int reqid, status;
+    int i, j, k, err, ncid, nok=0, nslabs, reqid;
+    double value[MAX_NELS], expect[MAX_NELS];
+    IntType m, start[MAX_RANK], index[MAX_RANK], index2[MAX_RANK];
+    IntType count[MAX_RANK], edge[MAX_RANK], mid[MAX_RANK], sstride[MAX_RANK];
+    PTRDType nstarts;   /* number of different starts */
+    PTRDType stride[MAX_RANK], imap[MAX_RANK];
     MPI_Datatype datatype;
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = APIFunc(iget_varm)(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = APIFunc(iget_varm)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
     for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = APIFunc(iget_varm)(BAD_ID, i, NULL, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        datatype = nc_mpi_type(var_type[i]);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
             imap[j] = 1;
         }
-        err = ncmpi_iget_varm(BAD_ID, i, start, edge, stride, imap, buf, 1, datatype, &reqid);
-        IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        err = APIFunc(iget_varm)(ncid, i, NULL, NULL, NULL, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        err = ncmpi_iget_varm(ncid, BAD_VARID, start, edge, stride, imap, buf, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+        err = APIFunc(iget_varm)(ncid, i, start, NULL, NULL, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE)
+            EXPECT_ERR(NC_EEDGE, err)
         ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS, first when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            start[j] = var_shape[i][j];    /* out of boundary check */
-            err = ncmpi_iget_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype, &reqid);
+            start[j] = var_shape[i][j];
+            err = APIFunc(iget_varm)(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
             IF (err != NC_EINVALCOORDS)
-                error("bad index: err = %d", err);
+                EXPECT_ERR(NC_EINVALCOORDS, err)
             ELSE_NOK
-
             start[j] = 0;
             edge[j] = var_shape[i][j] + 1;  /* edge error check */
-            err = ncmpi_iget_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype, &reqid);
+            err = APIFunc(iget_varm)(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
             IF (err != NC_EEDGE)
-                error("bad edge: err = %d", err);
+                EXPECT_ERR(NC_EEDGE, err)
             ELSE_NOK
             edge[j] = 1;
             stride[j] = 0;
-            err = ncmpi_iget_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype, &reqid);
+            err = APIFunc(iget_varm)(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
             IF (err != NC_ESTRIDE)
-                error("bad stride: err = %d", err);
+                EXPECT_ERR(NC_ESTRIDE, err)
             ELSE_NOK
             stride[j] = 1;
         }
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = APIFunc(iget_varm)(ncid, i, start, edge, stride, imap, value, 0, datatype, &reqid);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1;  /* out of boundary check */
+            err = APIFunc(iget_varm)(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
+        err = APIFunc(iget_varm)(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+        err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+
         /* Choose a random point dividing each dim into 2 parts */
         /* get 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -1251,10 +1662,8 @@ test_ncmpi_iget_varm(void)
             }
             for (m = 0; m < nstarts; m++) {
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
-                ELSE_NOK
-                nels = 1;
+                IF (err != 0) error("error in toMixedBase");
+                IntType nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
                     count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
                     index[j] += start[j];
@@ -1276,36 +1685,38 @@ test_ncmpi_iget_varm(void)
                         imap[j-1] = imap[j] * count[j];
                 }
                 for (j = 0; j < nels; j++) {
+                    int d;
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase 1");
-                    ELSE_NOK
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
                         index2[d] = index[d] + index2[d] * stride[d];
                     expect[j] = hash(var_type[i], var_rank[i], index2);
                 }
-                if (var_rank[i] == 0 && i%2 )
-                    err = ncmpi_iget_varm(ncid,i,NULL,NULL,NULL,NULL,buf, 1, datatype, &reqid);
-                else
-                    err = ncmpi_iget_varm(ncid,i,index,count,stride,imap,buf, nels, datatype, &reqid);
+                err = APIFunc(iget_varm)(ncid,i,index,count,stride,imap,value, nels, datatype, &reqid);
                 IF (err != NC_NOERR)
-                    error("%s", ncmpi_strerror(err));
+                    EXPECT_ERR(NC_NOERR, err)
                 ELSE_NOK
-
-                err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
                 IF (err != NC_NOERR)
-                    error("%s", ncmpi_strerror(err));
+                    EXPECT_ERR(NC_NOERR, err)
                 ELSE_NOK
 
-                num_err = 0;
                 for (j = 0; j < nels; j++) {
                     double got;
-                    char *p = (char *) buf;
+                    char *p = (char *) value;
                     p += j * nctypelen(var_type[i]);
                     if (inRange(expect[j],var_type[i])) {
                         err = nc2dbl(var_type[i], p, &got);
                         IF (err != NC_NOERR)
                             error("error in nc2dbl");
+                        ifelse(`$1', `uchar', `
+                        /* in put_vars(), API _put_vara_double() is used to
+                         * write the NC_BYTE variables to files. In this
+                         * case, NC_BYTE variables are treated as signed
+                         * for CDF-1 and 2 formats. Thus, we must skip the
+                         * equal test below for uchar.
+                         */
+                        if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
                         IF (!equal2(got,expect[j],var_type[i])) {
                             error("value read not that expected");
                             if (verbose) {
@@ -1316,17 +1727,16 @@ test_ncmpi_iget_varm(void)
                                 error("expect: %g, ", expect[j]);
                                 error("got: %g", got);
                             }
-                            num_err++;
                         }
+                        ELSE_NOK
                     }
-                    if (num_err == 0) nok++;
                 }
             }
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 
@@ -1335,82 +1745,182 @@ dnl
 define(`TEST_NC_IGET_VARM',dnl
 `dnl
 int
-test_ncmpi_iget_varm_$1(void)
+TestFunc(varm)_$1(VarArgs)
 {
-    int ncid;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err, num_err;
-    int allInExtRange;        /* all values within external range? */
-    int allInIntRange;        /* all values within internal range? */
-    int nels;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    MPI_Offset imap[MAX_RANK];
+    int i, k, err, nslabs, ncid, cdf_format, reqid;
+    int allInExtRange;  /* all values within external range? */
+    int allInIntRange;  /* all values within internal range? */
+    int nok = 0;        /* count of valid comparisons */
     int canConvert;     /* Both text or both numeric */
+    IntType j, m;
+    IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
+    IntType index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
+    IntType sstride[MAX_RANK];
+    PTRDType nstarts;   /* number of different starts */
+    PTRDType stride[MAX_RANK], imap[MAX_RANK];
     double expect[MAX_NELS];
     $1 value[MAX_NELS];
-    int reqid, status;
 
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(testfile, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = iGetVarm($1)(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = iGetVarm($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = iGetVarm($1)(BAD_ID, i, NULL, NULL, NULL, NULL, value, &reqid);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
             imap[j] = 1;
         }
-        err = ncmpi_iget_varm_$1(BAD_ID, i, start, edge, stride, imap, value, &reqid);
-        IF (err != NC_EBADID)
-            error("bad ncid: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        err = iGetVarm($1)(ncid, i, NULL, NULL, NULL, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EINVALCOORDS)
+            EXPECT_ERR(NC_EINVALCOORDS, err)
         ELSE_NOK
-        err = ncmpi_iget_varm_$1(ncid, BAD_VARID, start, edge, stride, imap, value, &reqid);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: err = %d", err);
+
+        err = iGetVarm($1)(ncid, i, start, NULL, NULL, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            index[0] = 0;
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        }
+        else IF (err != NC_EEDGE)
+            EXPECT_ERR(NC_EEDGE, err)
         ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS, NC_EEDGE and NC_ESTRIDE, first when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            start[j] = var_shape[i][j];    /* out of boundary check */
-            err = ncmpi_iget_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
+            start[j] = var_shape[i][j];
+            err = iGetVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
             if (!canConvert) {
                 IF (err != NC_ECHAR)
-                    error("conversion: err = %d", err);
-            } else {
-                IF (err != NC_EINVALCOORDS)
-                    error("bad index: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
-
                 start[j] = 0;
-                edge[j] = var_shape[i][j] + 1;  /* edge error check */
-                err = ncmpi_iget_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
-                IF (err != NC_EEDGE)
-                    error("bad edge: err = %d", err);
-                ELSE_NOK
-                edge[j] = 1;
-                stride[j] = 0;
-                err = ncmpi_iget_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
-                IF (err != NC_ESTRIDE)
-                    error("bad stride: err = %d", err);
+                continue;
+            }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = iGetVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;
+            err = iGetVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
+        }
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_rank[i] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = iGetVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
-                stride[j] = 1;
+                start[j] = 0;
+                continue;
+            }
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = iGetVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        err = iGetVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+        } else if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+            expect[0] = hash4(cdf_format, var_type[i], 0, index, NCT_ITYPE($1));
+            if (inRange3(cdf_format, expect[0], var_type[i], NCT_ITYPE($1)) &&
+                CheckRange($1, expect[0])) {
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
             }
+            else IF (err != NC_ERANGE) EXPECT_ERR(NC_ERANGE, err)
+        } else {
+            IF (err != NC_NOERR)
+                EXPECT_ERR(NC_NOERR, err)
         }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* get 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -1435,10 +1945,8 @@ test_ncmpi_iget_varm_$1(void)
             }
             for (m = 0; m < nstarts; m++) {
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
-                ELSE_NOK
-                nels = 1;
+                IF (err != 0) error("error in toMixedBase");
+                IntType nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
                     count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
                     nels *= count[j];
@@ -1461,46 +1969,49 @@ test_ncmpi_iget_varm_$1(void)
                 }
                 allInExtRange = allInIntRange = 1;
                 for (j = 0; j < nels; j++) {
+                    int d;
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase 1");
-                    ELSE_NOK
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
                         index2[d] = index[d] + index2[d] * stride[d];
-                    expect[j] = hash4(var_type[i], var_rank[i], index2,
+                    expect[j] = hash4(cdf_format, var_type[i], var_rank[i], index2,
                         NCT_ITYPE($1));
-                    if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) {
+                    if (inRange3(cdf_format, expect[j],var_type[i],NCT_ITYPE($1))) {
                         IfCheckTextChar($1, var_type[i])
                             allInIntRange &= CheckRange($1, expect[j]);
                     } else {
                         allInExtRange = 0;
                     }
                 }
-                if (var_rank[i] == 0 && i%2 )
-                    err = ncmpi_iget_varm_$1(ncid,i,NULL,NULL,NULL,NULL,value, &reqid);
-                else
-                    err = ncmpi_iget_varm_$1(ncid,i,index,count,stride,imap,value, &reqid);
-                if (err == NC_NOERR)
-                    ncmpi_wait_all(ncid, 1, &reqid, &status);
+                err = iGetVarm($1)(ncid,i,index,count,stride,imap,value, &reqid);
                 if (canConvert) {
+                    IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+                    err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
                     if (allInExtRange) {
                         if (allInIntRange) {
-                            IF (status != NC_NOERR)
-                                error("%s", ncmpi_strerror(status));
+                            IF (err != NC_NOERR)
+                                EXPECT_ERR(NC_NOERR, err)
                             ELSE_NOK
                         } else {
-                            IF (status != NC_ERANGE)
-                                error("Range error: status = %d", status);
+                            IF (err != NC_ERANGE)
+                                EXPECT_ERR(NC_ERANGE, err)
                             ELSE_NOK
                         }
                     } else {
-                        IF (status != NC_NOERR && status != NC_ERANGE)
-                            error("OK or Range error: status = %d", status);
+                        IF (err != NC_NOERR && err != NC_ERANGE)
+                            EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
                         ELSE_NOK
                     }
-                    num_err = 0;
                     for (j = 0; j < nels; j++) {
                         if (CheckNumRange($1, expect[j], var_type[i])) {
+                            ifelse(`$1', `uchar', `
+                            /* in put_vars(), API _put_vara_double() is used to
+                             * write the NC_BYTE variables to files. In this
+                             * case, NC_BYTE variables are treated as signed
+                             * for CDF-1 and 2 formats. Thus, we must skip the
+                             * equal test below for uchar.
+                             */
+                            if (cdf_format < NC_FORMAT_CDF5 && var_type[i] == NC_BYTE && expect[j] > schar_max) continue;')
                             IF (!equal(value[j],expect[j],var_type[i], NCT_ITYPE($1))){
                                 error("value read not that expected");
                                 if (verbose) {
@@ -1511,22 +2022,21 @@ test_ncmpi_iget_varm_$1(void)
                                     error("expect: %g, ", expect[j]);
                                     error("got: %g", (double) value[j]);
                                 }
-                                num_err++;
                             }
+                            ELSE_NOK
                         }
                     }
-                    if (num_err == 0) nok++;
                 } else {
-                    IF (nels > 0 && err != NC_ECHAR)
-                        error("wrong type: err = %d", err);
+                    IF (err != NC_ECHAR)
+                        EXPECT_ERR(NC_ECHAR, err)
                     ELSE_NOK
                 }
             }
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
diff --git a/test/nc_test/test_iput.m4 b/test/nc_test/test_iput.m4
index 9a5423e..d928384 100644
--- a/test/nc_test/test_iput.m4
+++ b/test/nc_test/test_iput.m4
@@ -1,6 +1,8 @@
 dnl This is m4 source.
 dnl Process using m4 to produce 'C' language file.
 dnl
+dnl This file is supposed to be the same as PnetCDF's test_iput.m4
+dnl
 dnl If you see this line, you can ignore the next one.
 /* Do not edit this file. It is produced from the corresponding .m4 source */
 dnl
@@ -8,8 +10,35 @@ dnl
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: test_iput.m4 2295 2016-01-06 20:28:09Z wkliao $ */
+/* $Id: test_iput.m4 2616 2016-11-14 09:19:14Z wkliao $ */
+
+dnl
+dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
+dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types
+dnl (MPI_Offset vs. size_t), and function name substrings for external data
+dnl types.
+dnl
+
+define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl
+
+define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl
+define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl
+define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_iput_$1',`test_nc_iput_$1')')dnl
+define(`APIFunc',` ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl
+
+define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, &ncid)', `file_open($1, $2, &ncid)')')dnl
+define(`FileCreate',`ifdef(`PNETCDF',`ncmpi_create(comm, $1, $2, info, &ncid)', `file_create($1, $2, &ncid)')')dnl
+define(`FileDelete',`ifdef(`PNETCDF',`ncmpi_delete($1,$2)',`nc_delete($1)')')dnl
+
+define(`VarArgs',   `ifdef(`PNETCDF',`int numVars',`void')')dnl
+define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts,int numVars',`void')')dnl
 
+define(`iPutVar1',`ifdef(`PNETCDF',`ncmpi_iput_var1_$1',`nc_iput_var1_$1')')dnl
+define(`iPutVar', `ifdef(`PNETCDF',`ncmpi_iput_var_$1', `nc_iput_var_$1')')dnl
+define(`iPutVara',`ifdef(`PNETCDF',`ncmpi_iput_vara_$1',`nc_iput_vara_$1')')dnl
+define(`iPutVars',`ifdef(`PNETCDF',`ncmpi_iput_vars_$1',`nc_iput_vars_$1')')dnl
+define(`iPutVarm',`ifdef(`PNETCDF',`ncmpi_iput_varm_$1',`nc_iput_varm_$1')')dnl
+define(`DefVars',`ifdef(`PNETCDF',`def_vars($1,$2)',`def_vars($1)')')dnl
 
 undefine(`index')dnl
 dnl dnl dnl
@@ -34,152 +63,14 @@ define(`CheckText', `ifelse(`$1',`text', , `== (NCT_ITYPE($1) == NCT_TEXT)')')dn
 define(`IfCheckTextChar', `ifelse(`$1',`text', `if ($2 != NC_CHAR)')')dnl
 define(`CheckNumRange',
        `ifelse(`$1',`text', `1',
-               `inRange3($2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
+               `inRange3(cdf_format, $2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
 define(`CheckRange3',
        `ifelse(`$1',`text', `1',
-               `inRange3($2,$3,NCT_ITYPE($1))')')dnl
+               `inRange3(cdf_format, $2,$3,NCT_ITYPE($1))')')dnl
 
 
 #include "tests.h"
 
-dnl HASH(TYPE)
-dnl
-define(`HASH',dnl
-`dnl
-/*
- *  ensure hash value within range for internal TYPE
- */
-static
-double
-hash_$1(
-    const nc_type type,
-    const int rank,
-    const MPI_Offset *index,
-    const nct_itype itype)
-{
-    const double min = $1_min;
-    const double max = $1_max;
-
-    return MAX(min, MIN(max, hash4( type, rank, index, itype)));
-}
-')dnl
-
-dnl HASH(text)
-#define hash_text hash4
-
-HASH(uchar)
-HASH(schar)
-HASH(short)
-HASH(int)
-HASH(long)
-HASH(float)
-HASH(double)
-HASH(ushort)
-HASH(uint)
-HASH(longlong)
-HASH(ulonglong)
-
-
-dnl CHECK_VARS(TYPE)
-dnl
-define(`CHECK_VARS',dnl
-`dnl
-/* 
- *  check all vars in file which are (text/numeric) compatible with TYPE
- */
-static
-int
-check_vars_$1(const char *filename)
-{
-    int  ncid;                  /* netCDF id */
-    MPI_Offset index[MAX_RANK];
-    int  err;           /* status */
-    int  d;
-    int  i;
-    size_t  j;
-    $1 value;
-    nc_type datatype;
-    int ndims;
-    int dimids[MAX_RANK];
-    char name[NC_MAX_NAME];
-    MPI_Offset length;
-    int canConvert;     /* Both text or both numeric */
-    int nok = 0;      /* count of valid comparisons */
-    double expect;
-
-    err = ncmpi_open(comm, filename, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-
-    for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
-        if (canConvert) {
-            err = ncmpi_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
-            IF (err != NC_NOERR)
-                error("ncmpi_inq_var: %s", ncmpi_strerror(err));
-            IF (strcmp(name, var_name[i]) != 0)
-                error("Unexpected var_name");
-            IF (datatype != var_type[i])
-                error("Unexpected type");
-            IF (ndims != var_rank[i])
-                error("Unexpected rank");
-            for (j = 0; j < ndims; j++) {
-                err = ncmpi_inq_dim(ncid, dimids[j], 0, &length);
-                IF (err != NC_NOERR)
-                    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
-                IF (length != var_shape[i][j])
-                    error("Unexpected shape");
-            }
-            for (j = 0; j < var_nels[i]; j++) {
-                err = toMixedBase(j, var_rank[i], var_shape[i], index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase 2");
-                expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1));
-                err = ncmpi_get_var1_$1_all(ncid, i, index, &value);
-                if (CheckNumRange($1, expect, datatype)) {
-                    IF (err != NC_NOERR) {
-                        error("error in ncmpi_get_var1_$1_all $s",__func__);
-                    } else IF (!equal(value,expect,var_type[i],NCT_ITYPE($1))) {
-                        error("Var value read not that expected");
-                        if (verbose) {
-                            error("\n");
-                            error("varid: %d, ", i);
-                            error("var_name: %s, ", var_name[i]);
-                            error("var_type: %s, ", s_nc_type(var_type[i]));
-                            error("put type: $1, ");
-                            error("index:");
-                            for (d = 0; d < var_rank[i]; d++)
-                                error(" %d", index[d]);
-                            error(", expect: %g, ", expect);
-                            error("got: %g", (double) value);
-                        }
-                    } else {
-                        ++nok;
-                    }
-                }
-            }
-        }
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-')dnl
-
-CHECK_VARS(text)
-CHECK_VARS(uchar)
-CHECK_VARS(schar)
-CHECK_VARS(short)
-CHECK_VARS(int)
-CHECK_VARS(long)
-CHECK_VARS(float)
-CHECK_VARS(double)
-CHECK_VARS(ushort)
-CHECK_VARS(uint)
-CHECK_VARS(longlong)
-CHECK_VARS(ulonglong)
-
 static double
 hash2nc(const nc_type var_type, int var_rank, MPI_Offset *index)
 {
@@ -232,185 +123,259 @@ dbls2ncs(int nels, int var_type, double *inBuf, void *outBuf)
 }
 
 int
-test_ncmpi_iput_var1(void)
+TestFunc(var1)(VarArgs)
 {
-    int ncid, nok=0;
-    int i;
-    int j;
-    int err;
-    MPI_Offset index[MAX_RANK];
-    double value = 5;        /* any value would do - only for error cases */
-    int reqid, status=NC_NOERR;
+    int i, err, ncid, nok=0, reqid, status;
+    IntType j, index[MAX_RANK];
     MPI_Datatype datatype;
+    double value[1];
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = APIFunc(iput_var1)(BAD_ID, 0, NULL, NULL, 1, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = APIFunc(iput_var1)(ncid, BAD_VARID, NULL, NULL, 1, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
-        for (j = 0; j < var_rank[i]; j++)
-            index[j] = 0;
-        err = ncmpi_iput_var1(BAD_ID, i, index, &value, 1, datatype, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = APIFunc(iput_var1)(BAD_ID, i, NULL, value, 1, MPI_DATATYPE_NULL, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
         ELSE_NOK
-        err = ncmpi_iput_var1(ncid, BAD_VARID, index, &value, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
+
+        datatype = nc_mpi_type(var_type[i]);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = APIFunc(iput_var1)(ncid, i, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS */
+        for (j = 0; j < var_rank[i]; j++) index[j] = 0;
+
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                index[j] = var_shape[i][j];     /* out of boundary check */
-                err = ncmpi_iput_var1(ncid, i, index, &value, 1, datatype, &reqid);
-                IF (err != NC_EINVALCOORDS)
-                    error("bad index: err = %d", err);
-                ELSE_NOK
-                index[j] = 0;
-            }
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            index[j] = var_shape[i][j]; /* out of boundary check */
+            err = APIFunc(iput_var1)(ncid, i, index, value, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            index[j] = 0;
         }
+
         for (j = 0; j < var_nels[i]; j++) {
             double buf;
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR) 
-                error("error in toMixedBase 1");
-            value = hash2nc(var_type[i], var_rank[i], index);
-            err = dbl2nc(value, var_type[i], &buf);
+            IF (err != 0) error("error in toMixedBase");
+            value[0] = hash2nc(var_type[i], var_rank[i], index);
+            err = dbl2nc(value[0], var_type[i], &buf);
             IF (err != NC_NOERR)
                 error("error in dbl2nc");
 
-            if (var_rank[i] == 0 && i%2 == 0)
-                err = ncmpi_iput_var1(ncid, i, NULL, &buf, 1, datatype, &reqid);
-            else
-                err = ncmpi_iput_var1(ncid, i, index, &buf, 1, datatype, &reqid);
+            err = APIFunc(iput_var1)(ncid, i, index, &buf, 1, datatype, &reqid);
             IF (err != NC_NOERR)
-                error("ncmpi_iput_var1: %s", ncmpi_strerror(err));
+                error("iput_var1: %s", APIFunc(strerror)(err));
             ELSE_NOK
 
-            err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+            err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
             IF (err != NC_NOERR)
-                error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+                error("wait_all: err=%s", APIFunc(strerror)(err));
+            else IF (status != NC_NOERR)
+                error("wait_all: status=%s", APIFunc(strerror)(status));
             ELSE_NOK
         }
     }
 
-    check_vars(ncid);
+    nok += check_vars(ncid, numVars);
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 
-dnl TEST_NC_IPUT_VAR1(TYPE)
 dnl
 define(`TEST_NC_IPUT_VAR1',dnl
 `dnl
 int
-test_ncmpi_iput_var1_$1(void)
+TestFunc(var1)_$1(VarArgs)
 {
-    int ncid, nok=0;
-    int i;
-    int j;
-    int err;
-    MPI_Offset index[MAX_RANK];
-    int canConvert;        /* Both text or both numeric */
-    $1 value = 5;        /* any value would do - only for error cases */
-    int reqid, status=NC_NOERR;
-
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    int i, err, ncid, cdf_format, nok=0, reqid, status;
+    int canConvert;      /* Both text or both numeric */
+    IntType j, index[MAX_RANK];
+    $1 value[1];
+
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = iPutVar1($1)(BAD_ID, 0, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = iPutVar1($1)(ncid, BAD_VARID, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
-        for (j = 0; j < var_rank[i]; j++)
-            index[j] = 0;
-        err = ncmpi_iput_var1_$1(BAD_ID, i, index, &value, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = iPutVar1($1)(BAD_ID, i, NULL, value, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
         ELSE_NOK
-        err = ncmpi_iput_var1_$1(ncid, BAD_VARID, index, &value, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = iPutVar1($1)(ncid, i, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS */
+        for (j = 0; j < var_rank[i]; j++) index[j] = 0;
+
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                index[j] = var_shape[i][j];     /* out of boundary check */
-                err = ncmpi_iput_var1_$1(ncid, i, index, &value, &reqid);
-                IF (canConvert && err != NC_EINVALCOORDS)
-                    error("bad index: err = %d", err);
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            index[j] = var_shape[i][j]; /* out of boundary check */
+            err = iPutVar1($1)(ncid, i, index, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
-                if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
                 index[j] = 0;
+                continue;
             }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            index[j] = 0;
         }
+
         for (j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR) 
-                error("error in toMixedBase 1");
-            value = hash_$1( var_type[i], var_rank[i], index, NCT_ITYPE($1));
-            if (var_rank[i] == 0 && i%2 == 0)
-                err = ncmpi_iput_var1_$1(ncid, i, NULL, &value, &reqid);
-            else
-                err = ncmpi_iput_var1_$1(ncid, i, index, &value, &reqid);
-            if (err == NC_NOERR || err == NC_ERANGE)
-                /* NC_ERANGE is not fatal, must continue */
-                ncmpi_wait_all(ncid, 1, &reqid, &status);
+            IF (err != 0) error("error in toMixedBase");
+            value[0] = hash_$1(cdf_format, var_type[i], var_rank[i], index,
+                               NCT_ITYPE($1));
+            err = iPutVar1($1)(ncid, i, index, value, &reqid);
             if (canConvert) {
-                if (CheckRange3($1, value, var_type[i])) {
+                if (CheckRange3($1, value[0], var_type[i])) {
                     IF (err != NC_NOERR)
-                        error("%s", ncmpi_strerror(err));
-                    ELSE_NOK
-                    IF (status != NC_NOERR)
-                        error("%s", ncmpi_strerror(status));
-                    ELSE_NOK
+                        error("%s", APIFunc(strerror)(err));
+                    else {
+                        err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                        IF (err != NC_NOERR)
+                            error("wait_all: err=%s", APIFunc(strerror)(err));
+                        else IF (status != NC_NOERR)
+                            error("wait_all: status=%s", APIFunc(strerror)(status));
+                    }
                 } else {
-                    /* NC_ERANGE is checked at ncmpi_iput_var1_$1() */
                     IF (err != NC_ERANGE) {
-                        error("Range error: err = %d", err);
+                        EXPECT_ERR(NC_ERANGE, err)
                         error("\n\t\tfor type %s value %.17e %ld",
                                 s_nc_type(var_type[i]),
-                                (double)value, (long)value, &reqid);
+                                (double)value[0], (long)value[0]);
+                    }
+                    else { /* NC_ERANGE does not invalidate the nonblocking
+                            * request, the request is still posted */
+                        err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                        IF (err != NC_NOERR)
+                            error("wait_all: err=%s", APIFunc(strerror)(err));
+                        else IF (status != NC_NOERR)
+                            error("wait_all: status=%s", APIFunc(strerror)(status));
                     }
-                    ELSE_NOK
                 }
             } else {
-                /* NC_ECHAR is checked at ncmpi_iput_var1_$1() */
                 IF (err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
             }
         }
     }
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    nok += check_vars_$1(scratch);
+    nok += check_vars_$1(scratch, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
@@ -429,172 +394,198 @@ TEST_NC_IPUT_VAR1(longlong)
 TEST_NC_IPUT_VAR1(ulonglong)
 
 int
-test_ncmpi_iput_var(void)
+TestFunc(var)(VarArgs)
 {
-    int ncid, nok=0, varid, i, j, err, nels;
-    MPI_Offset index[MAX_RANK];
-    double value[MAX_NELS];
-    int reqid, status=NC_NOERR;
+    int i, err, ncid, varid, nok=0, reqid, status;
+    IntType j, index[MAX_RANK];
     MPI_Datatype datatype;
+    double value[MAX_NELS], ncbuf[MAX_NELS];
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = APIFunc(iput_var)(BAD_ID, 0, NULL, 1, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = APIFunc(iput_var)(ncid, BAD_VARID, NULL, 1, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     /* Because var API is writing the entire variables. We need at first
      * make sure there are non-zero records to write */
 
     /* Write record number NRECS to force writing of preceding records */
     /* Assumes variable cr is char vector with UNLIMITED dimension */
-    err = ncmpi_inq_varid(ncid, "cr", &varid);
+    err = APIFunc(inq_varid)(ncid, "cr", &varid);
     IF (err != NC_NOERR)
-        error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+        error("inq_varid: %s", APIFunc(strerror)(err));
     index[0] = NRECS-1;
-    err = ncmpi_iput_var1_text(ncid, varid, index, "x", &reqid);
+    err = APIFunc(iput_var1_text)(ncid, varid, index, "x", &reqid);
     IF (err != NC_NOERR)
-        error("ncmpi_iput_var1_text: %s", ncmpi_strerror(err));
-    err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+        error("iput_var1_text: %s", APIFunc(strerror)(err));
+    err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
     IF (err != NC_NOERR)
-        error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+        error("wait_all: %s", APIFunc(strerror)(err));
 
     for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
-        err = ncmpi_iput_var(BAD_ID, i, value, 1, datatype, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
-        ELSE_NOK
-        err = ncmpi_iput_var(ncid, BAD_VARID, value, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = APIFunc(iput_var)(BAD_ID, i, value, 1, MPI_DATATYPE_NULL, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
         ELSE_NOK
 
-        nels = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            nels *= var_shape[i][j];
-            index[j] = 0;
-        }
-        double ncbuf[MAX_NELS];
-        for (j = 0; j < nels; j++) {
+        datatype = nc_mpi_type(var_type[i]);
+
+        for (j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR) 
-                error("error in toMixedBase 1");
+            IF (err != 0) error("error in toMixedBase");
             ncbuf[j] = hash2nc(var_type[i], var_rank[i], index);
         }
         /* type convert ncbuf[] to value[] */
-        err = dbls2ncs(nels, var_type[i], ncbuf, value);
-        IF (err != NC_NOERR) 
+        err = dbls2ncs(var_nels[i], var_type[i], ncbuf, value);
+        IF (err != NC_NOERR)
             error("error in dbls2ncs");
-        err = ncmpi_iput_var(ncid, i, value, nels, datatype, &reqid);
+
+        err = APIFunc(iput_var)(ncid, i, value, var_nels[i], datatype, &reqid);
         IF (err != NC_NOERR)
-            error("ncmpi_iput_var: %s", ncmpi_strerror(err));
+            error("iput_var: %s", APIFunc(strerror)(err));
         ELSE_NOK
 
-        err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+        err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
         IF (err != NC_NOERR)
-            error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+            error("wait_all: %s", APIFunc(strerror)(err));
         ELSE_NOK
     }
 
-    check_vars(ncid);
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    nok += check_vars(ncid, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("close: %s", APIFunc(strerror)(err));
 
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("delete file %s failed", scratch);
     return nok;
 }
 
-dnl TEST_NC_IPUT_VAR(TYPE)
 dnl
 define(`TEST_NC_IPUT_VAR',dnl
 `dnl
 int
-test_ncmpi_iput_var_$1(void)
+TestFunc(var)_$1(VarArgs)
 {
-    int ncid, nok=0;
-    int varid;
-    int i;
-    int j;
-    int err;
-    int nels;
-    MPI_Offset index[MAX_RANK];
-    int canConvert;        /* Both text or both numeric */
-    int allInExtRange;        /* all values within external range? */
+    int i, err, ncid, varid, cdf_format, nok=0, reqid, status;
+    int canConvert;      /* Both text or both numeric */
+    int allInExtRange;   /* all values within external range? */
+    IntType j, index[MAX_RANK];
     $1 value[MAX_NELS];
-    int reqid, status=NC_NOERR;
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = iPutVar($1)(BAD_ID, 0, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = iPutVar($1)(ncid, BAD_VARID, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
-        err = ncmpi_iput_var_$1(BAD_ID, i, value, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
-        ELSE_NOK
-        err = ncmpi_iput_var_$1(ncid, BAD_VARID, value, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
+
+        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = iPutVar($1)(BAD_ID, i, value, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
         ELSE_NOK
 
-        nels = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            nels *= var_shape[i][j];
-        }
-        for (allInExtRange = 1, j = 0; j < nels; j++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
+        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR) 
-                error("error in toMixedBase 1");
-            value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+            IF (err != 0) error("error in toMixedBase");
+            value[j]= hash_$1(cdf_format, var_type[i], var_rank[i], index,
+                              NCT_ITYPE($1));
             IfCheckTextChar($1, var_type[i])
-                allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                allInExtRange &= inRange3(cdf_format, (double)value[j],
+                                          var_type[i], NCT_ITYPE($1));
         }
-        err = ncmpi_iput_var_$1(ncid, i, value, &reqid);
-        if (err == NC_NOERR || err == NC_ERANGE)
-            /* NC_ERANGE is not fatal, must continue */
-            ncmpi_wait_all(ncid, 1, &reqid, &status);
-
+        err = iPutVar($1)(ncid, i, value, &reqid);
         if (canConvert) {
             if (allInExtRange) {
-                IF (err != NC_NOERR) 
-                    error("%s", ncmpi_strerror(err));
-                ELSE_NOK
-                IF (status != NC_NOERR) 
-                    error("%s", ncmpi_strerror(status));
-                ELSE_NOK
+                IF (err != NC_NOERR)
+                    error("%s", APIFunc(strerror)(err));
+                else {
+                    err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                    IF (err != NC_NOERR)
+                        error("wait_all: err=%s", APIFunc(strerror)(err));
+                    else IF (status != NC_NOERR)
+                        error("wait_all: status=%s", APIFunc(strerror)(status));
+                }
             } else {
-                /* NC_ERANGE is checked at ncmpi_iput_var_$1() */
-                IF (err != NC_ERANGE && var_dimid[i][0] != RECDIM)
-                    error("expecting range error, but err = %d", err);
-                ELSE_NOK
+                IF (err != NC_ERANGE) {
+                    EXPECT_ERR(NC_ERANGE, err)
+                    error("\n\t\tfor type %s value %.17e %ld",
+                          s_nc_type(var_type[i]),
+                          (double)value[0], (long)value[0]);
+                }
+                else { /* NC_ERANGE does not invalidate the nonblocking
+                        * request, the request is still posted */
+                    err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                    IF (err != NC_NOERR)
+                        error("wait_all: err=%s", APIFunc(strerror)(err));
+                    else IF (status != NC_NOERR)
+                        error("wait_all: status=%s", APIFunc(strerror)(status));
+                }
             }
-        } else { /* should flag wrong type even if nothing to write */
-            /* NC_ECHAR is checked at ncmpi_iput_var_$1() */
-            IF (nels > 0 && err != NC_ECHAR)
-                error("wrong type: err = %d", err);
+        } else {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
             ELSE_NOK
         }
     }
@@ -604,76 +595,81 @@ test_ncmpi_iput_var_$1(void)
 
     /* Write record number NRECS to force writing of preceding records */
     /* Assumes variable cr is char vector with UNLIMITED dimension */
-    err = ncmpi_inq_varid(ncid, "cr", &varid);
+    err = APIFunc(inq_varid)(ncid, "cr", &varid);
     IF (err != NC_NOERR)
-        error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+        error("inq_varid: %s", APIFunc(strerror)(err));
     index[0] = NRECS-1;
-    err = ncmpi_iput_var1_text(ncid, varid, index, "x", &reqid);
+    err = APIFunc(iput_var1_text)(ncid, varid, index, "x", &reqid);
     IF (err != NC_NOERR)
-        error("ncmpi_iput_var1_text: %s", ncmpi_strerror(err));
-    else
-        ncmpi_wait_all(ncid, 1, &reqid, &status);
+        error("iput_var1_text: %s", APIFunc(strerror)(err));
+    else {
+        err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+        IF (err != NC_NOERR)
+            error("wait_all: err=%s", APIFunc(strerror)(err));
+        else IF (status != NC_NOERR)
+            error("wait_all: status=%s", APIFunc(strerror)(status));
+    }
 
     for (i = 0; i < numVars; i++) {
-        if (var_dimid[i][0] == RECDIM) {  /* only test record variables here */
-            canConvert = (var_type[i] == NC_CHAR) CheckText($1);
-            assert(var_rank[i] <= MAX_RANK);
-            assert(var_nels[i] <= MAX_NELS);
-            err = ncmpi_iput_var_$1(BAD_ID, i, value, &reqid);
-            IF (err != NC_EBADID) 
-                error("expecting bad ncid, but err = %d", err);
-            ELSE_NOK
+        if (var_dimid[i][0] != RECDIM) continue;  /* only test record variables */
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
 
-            nels = 1;
-            for (j = 0; j < var_rank[i]; j++) {
-                nels *= var_shape[i][j];
-            }
-            for (allInExtRange = 1, j = 0; j < nels; j++) {
-                err = toMixedBase(j, var_rank[i], var_shape[i], index);
-                IF (err != NC_NOERR) 
-                    error("error in toMixedBase 1");
-                ELSE_NOK
-                value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
-                IfCheckTextChar($1, var_type[i])
-                    allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
-            }
-            err = ncmpi_iput_var_$1(ncid, i, value, &reqid);
-            if (err == NC_NOERR || err == NC_ERANGE)
-                /* NC_ERANGE is not fatal, must continue */
-                ncmpi_wait_all(ncid, 1, &reqid, &status);
-            if (canConvert) {
-                if (allInExtRange) {
-                    IF (err != NC_NOERR) 
-                        error("%s", ncmpi_strerror(err));
-                    ELSE_NOK
-                    IF (status != NC_NOERR) 
-                        error("%s", ncmpi_strerror(status));
-                    ELSE_NOK
-                } else {
-                    /* NC_ERANGE is checked at ncmpi_iput_var_$1() */
-                    IF (err != NC_ERANGE)
-                        error("range error: err = %d", err);
-                    ELSE_NOK
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
+        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != 0) error("error in toMixedBase");
+            value[j]= hash_$1(cdf_format, var_type[i], var_rank[i], index,
+                              NCT_ITYPE($1));
+            IfCheckTextChar($1, var_type[i])
+                allInExtRange &= inRange3(cdf_format, (double)value[j],
+                                          var_type[i], NCT_ITYPE($1));
+        }
+        err = iPutVar($1)(ncid, i, value, &reqid);
+        if (canConvert) {
+            if (allInExtRange) {
+                IF (err != NC_NOERR)
+                    error("%s", APIFunc(strerror)(err));
+                else {
+                    err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                    IF (err != NC_NOERR)
+                        error("wait_all: err=%s", APIFunc(strerror)(err));
+                    else IF (status != NC_NOERR)
+                        error("wait_all: status=%s", APIFunc(strerror)(status));
                 }
             } else {
-                /* NC_ECHAR is checked at ncmpi_iput_var_$1() */
-                IF (nels > 0 && err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
-                ELSE_NOK
+                IF (err != NC_ERANGE) {
+                    EXPECT_ERR(NC_ERANGE, err)
+                    error("\n\t\tfor type %s value %.17e %ld",
+                          s_nc_type(var_type[i]),
+                          (double)value[0], (long)value[0]);
+                }
+                else { /* NC_ERANGE does not invalidate the nonblocking
+                        * request, the request is still posted */
+                    err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                    IF (err != NC_NOERR)
+                        error("wait_all: err=%s", APIFunc(strerror)(err));
+                    else IF (status != NC_NOERR)
+                        error("wait_all: status=%s", APIFunc(strerror)(status));
+                }
             }
+        } else {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
         }
     }
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    nok += check_vars_$1(scratch);
+    nok += check_vars_$1(scratch, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
@@ -692,88 +688,127 @@ TEST_NC_IPUT_VAR(longlong)
 TEST_NC_IPUT_VAR(ulonglong)
 
 int
-test_ncmpi_iput_vara(void)
+TestFunc(vara)(VarArgs)
 {
-    int ncid, nok=0, d, i, j, k, err, nslabs, nels;
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    double value[MAX_NELS];
-    int reqid, status=NC_NOERR;
+    int i, j, k, err, ncid, nok=0, nslabs, reqid, status;
+    double value[MAX_NELS], ncbuf[MAX_NELS];
+    IntType start[MAX_RANK], edge[MAX_RANK], mid[MAX_RANK], index[MAX_RANK];
     MPI_Datatype datatype;
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = APIFunc(iput_vara)(BAD_ID, 0, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = APIFunc(iput_vara)(ncid, BAD_VARID, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
-    value[0] = 0;
     for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = APIFunc(iput_vara)(BAD_ID, i, NULL, NULL, value, 1, MPI_DATATYPE_NULL, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        datatype = nc_mpi_type(var_type[i]);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
         }
-        err = ncmpi_iput_vara(BAD_ID, i, start, edge, value, 1, datatype, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
-        ELSE_NOK
-        err = ncmpi_iput_vara(ncid, BAD_VARID, start, edge, value, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
-        ELSE_NOK
-        for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];      /* out of bundary check */
-                err = ncmpi_iput_vara(ncid, i, start, edge, value, 1, datatype, &reqid);
-                IF (err != NC_EINVALCOORDS)
-                    error("expecting bad start, but err = %d", err);
-                ELSE_NOK
-                start[j] = 0;
-                edge[j] = var_shape[i][j] + 1;  /* edge error check */
-                err = ncmpi_iput_vara(ncid, i, start, edge, value, 1, datatype, &reqid);
-                IF (err != NC_EEDGE)
-                    error("expecting bad edge, but err = %d", err);
-                ELSE_NOK
-                edge[j] = 1;
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = APIFunc(iput_vara)(ncid, i, NULL, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
             }
         }
-        /* Check correct error returned even when nothing to put */
-        for (j = 0; j < var_rank[i]; j++) {
-            edge[j] = 0;
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
         }
-        err = ncmpi_iput_vara(BAD_ID, i, start, edge, value, 1, datatype, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
         ELSE_NOK
-        err = ncmpi_iput_vara(ncid, BAD_VARID, start, edge, value, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
-        ELSE_NOK
-        for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];     /* out of boundary check */
-                err = ncmpi_iput_vara(ncid, i, start, edge, value, 1, datatype, &reqid);
-                IF (err != NC_EINVALCOORDS)
-                    error("bad start: err = %d", err);
-                ELSE_NOK
-                start[j] = 0;
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = APIFunc(iput_vara)(ncid, i, start, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
             }
         }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
+        ELSE_NOK
+')dnl
 
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = APIFunc(iput_vara)(ncid, i, start, edge, value, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;
+            err = APIFunc(iput_vara)(ncid, i, start, edge, value, 1, datatype, &reqid);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDG, err)
+            ELSE_NOK
             edge[j] = 1;
         }
 
+        /* Check correct error returned when nothing to put, when edge[*]==0 */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = APIFunc(iput_vara)(ncid, i, start, edge, value, 0, datatype, &reqid);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = APIFunc(iput_vara)(ncid, i, start, edge, value, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* Put 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -783,7 +818,7 @@ test_ncmpi_iput_vara(void)
         }
         /* bits of k determine whether to put lower or upper part of dim */
         for (k = 0; k < nslabs; k++) {
-            nels = 1;
+            IntType nels = 1;
             for (j = 0; j < var_rank[i]; j++) {
                 if ((k >> j) & 1) {
                     start[j] = 0;
@@ -794,13 +829,11 @@ test_ncmpi_iput_vara(void)
                 }
                 nels *= edge[j];
             }
-            double ncbuf[MAX_NELS];
             for (j = 0; j < nels; j++) {
+                int d;
                 err = toMixedBase(j, var_rank[i], edge, index);
-                IF (err != NC_NOERR) 
-                    error("error in toMixedBase 1");
-                ELSE_NOK
-                for (d = 0; d < var_rank[i]; d++) 
+                IF (err != 0) error("error in toMixedBase");
+                for (d = 0; d < var_rank[i]; d++)
                     index[d] += start[d];
                 ncbuf[j] = hash2nc(var_type[i], var_rank[i], index);
             }
@@ -809,130 +842,183 @@ test_ncmpi_iput_vara(void)
             IF (err != NC_NOERR)
                 error("error in dbls2ncs");
 
-            if (var_rank[i] == 0 && i%2 == 0)
-                err = ncmpi_iput_vara(ncid, i, NULL, NULL, value, nels, datatype, &reqid);
-            else
-                err = ncmpi_iput_vara(ncid, i, start, edge, value, nels, datatype, &reqid);
+            err = APIFunc(iput_vara)(ncid, i, start, edge, value, nels, datatype, &reqid);
             IF (err != NC_NOERR)
-                error("ncmpi_iput_var1: %s", ncmpi_strerror(err));
+                error("iput_vara: %s", APIFunc(strerror)(err));
             ELSE_NOK
 
-            err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+            err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
             IF (err != NC_NOERR)
-                error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+                error("wait_all: err=%s", APIFunc(strerror)(err));
+            else IF (status != NC_NOERR)
+                error("wait_all: status=%s", APIFunc(strerror)(status));
             ELSE_NOK
         }
     }
 
-    check_vars(ncid);
+    nok += check_vars(ncid, numVars);
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 
-dnl TEST_NC_IPUT_VARA(TYPE)
 dnl
 define(`TEST_NC_IPUT_VARA',dnl
 `dnl
 int
-test_ncmpi_iput_vara_$1(void)
+TestFunc(vara)_$1(VarArgs)
 {
-    int ncid, nok=0;
-    int d;
-    int i;
-    int j;
-    int k;
-    int err;
-    int nslabs;
-    int nels;
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    int canConvert;        /* Both text or both numeric */
-    int allInExtRange;        /* all values within external range? */
+    int i, k, err, ncid, cdf_format, nslabs, nok=0, reqid, status;
+    int canConvert;      /* Both text or both numeric */
+    int allInExtRange;   /* all values within external range? */
+    IntType j;
+    IntType start[MAX_RANK], edge[MAX_RANK], mid[MAX_RANK], index[MAX_RANK];
     $1 value[MAX_NELS];
-    int reqid, status=NC_NOERR;
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = iPutVara($1)(BAD_ID, 0, NULL, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = iPutVara($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
-    value[0] = 0;
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = iPutVara($1)(BAD_ID, i, NULL, NULL, value, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
         }
-        err = ncmpi_iput_vara_$1(BAD_ID, i, start, edge, value, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
-        ELSE_NOK
-        err = ncmpi_iput_vara_$1(ncid, BAD_VARID, start, edge, value, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
-        ELSE_NOK
-        for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];      /* out of bundary check */
-                err = ncmpi_iput_vara_$1(ncid, i, start, edge, value, &reqid);
-                IF (canConvert && err != NC_EINVALCOORDS)
-                    error("expecting bad start, but err = %d", err);
-                ELSE_NOK
-                if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
-                start[j] = 0;
-                edge[j] = var_shape[i][j] + 1;  /* edge error check */
-                err = ncmpi_iput_vara_$1(ncid, i, start, edge, value, &reqid);
-                IF (canConvert && err != NC_EEDGE)
-                    error("expecting bad edge, but err = %d", err);
-                ELSE_NOK
-                if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
-                edge[j] = 1;
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = iPutVara($1)(ncid, i, NULL, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
             }
         }
-        /* Check correct error returned even when nothing to put */
-        for (j = 0; j < var_rank[i]; j++) {
-            edge[j] = 0;
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
         }
-        err = ncmpi_iput_vara_$1(BAD_ID, i, start, edge, value, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
         ELSE_NOK
-        err = ncmpi_iput_vara_$1(ncid, BAD_VARID, start, edge, value, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = iPutVara($1)(ncid, i, start, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];     /* out of boundary check */
-                err = ncmpi_iput_vara_$1(ncid, i, start, edge, value, &reqid);
-                IF (canConvert && err != NC_EINVALCOORDS)
-                    error("bad start: err = %d", err);
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = iPutVara($1)(ncid, i, start, edge, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
-                if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
                 start[j] = 0;
+                continue;
             }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = iPutVara($1)(ncid, i, start, edge, value, &reqid);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            ELSE_NOK
+            edge[j] = 1;
         }
 
+        /* Check correct error returned when nothing to put, when edge[*]==0 */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
         for (j = 0; j < var_rank[i]; j++) {
-            edge[j] = 1;
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = iPutVara($1)(ncid, i, start, edge, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
+                start[j] = 0;
+                continue;
+            }
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1;     /* out of boundary check */
+            err = iPutVara($1)(ncid, i, start, edge, value, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
         }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
 
         /* Choose a random point dividing each dim into 2 parts */
         /* Put 2^rank (nslabs) slabs so defined */
@@ -943,7 +1029,7 @@ test_ncmpi_iput_vara_$1(void)
         }
         /* bits of k determine whether to put lower or upper part of dim */
         for (k = 0; k < nslabs; k++) {
-            nels = 1;
+            IntType nels = 1;
             for (j = 0; j < var_rank[i]; j++) {
                 if ((k >> j) & 1) {
                     start[j] = 0;
@@ -955,55 +1041,58 @@ test_ncmpi_iput_vara_$1(void)
                 nels *= edge[j];
             }
             for (allInExtRange = 1, j = 0; j < nels; j++) {
+                int d;
                 err = toMixedBase(j, var_rank[i], edge, index);
-                IF (err != NC_NOERR) 
-                    error("error in toMixedBase 1");
-                ELSE_NOK
-                for (d = 0; d < var_rank[i]; d++) 
+                IF (err != 0) error("error in toMixedBase");
+                for (d = 0; d < var_rank[i]; d++)
                     index[d] += start[d];
-                value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+                value[j]= hash_$1(cdf_format, var_type[i], var_rank[i], index,
+                                  NCT_ITYPE($1));
                 IfCheckTextChar($1, var_type[i])
-                    allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                    allInExtRange &= inRange3(cdf_format, (double)value[j],
+                                              var_type[i], NCT_ITYPE($1));
             }
-            if (var_rank[i] == 0 && i%2 == 0)
-                err = ncmpi_iput_vara_$1(ncid, i, NULL, NULL, value, &reqid);
-            else
-                err = ncmpi_iput_vara_$1(ncid, i, start, edge, value, &reqid);
-            if (err == NC_NOERR || err == NC_ERANGE)
-                /* NC_ERANGE is not fatal, must continue */
-                ncmpi_wait_all(ncid, 1, &reqid, &status);
+            err = iPutVara($1)(ncid, i, start, edge, value, &reqid);
             if (canConvert) {
                 if (allInExtRange) {
-                    IF (err != NC_NOERR) 
-                        error("%s", ncmpi_strerror(err));
-                    ELSE_NOK
-                    IF (status != NC_NOERR) 
-                        error("%s", ncmpi_strerror(status));
-                    ELSE_NOK
+                    IF (err != NC_NOERR)
+                        EXPECT_ERR(NC_NOERR, err)
+                    else {
+                        err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                        IF (err != NC_NOERR)
+                            error("wait_all: err=%s", APIFunc(strerror)(err));
+                        else IF (status != NC_NOERR)
+                            error("wait_all: status=%s", APIFunc(strerror)(status));
+                    }
                 } else {
-                    /* NC_ERANGE is checked at ncmpi_iput_vara_$1() */
                     IF (err != NC_ERANGE)
-                        error("range error: err = %d", err);
-                    ELSE_NOK
+                        EXPECT_ERR(NC_ERANGE, err)
+                    else { /* NC_ERANGE does not invalidate the nonblocking
+                            * request, the request is still posted */
+                        err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                        IF (err != NC_NOERR)
+                            error("wait_all: err=%s", APIFunc(strerror)(err));
+                        else IF (status != NC_NOERR)
+                            error("wait_all: status=%s", APIFunc(strerror)(status));
+                    }
                 }
             } else {
-                /* NC_ECHAR is checked at ncmpi_iput_vara_$1() */
-                IF (nels > 0 && err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
             }
         }
     }
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    nok += check_vars_$1(scratch);
+    nok += check_vars_$1(scratch, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
@@ -1022,72 +1111,135 @@ TEST_NC_IPUT_VARA(longlong)
 TEST_NC_IPUT_VARA(ulonglong)
 
 int
-test_ncmpi_iput_vars(void)
+TestFunc(vars)(VarArgs)
 {
-    int ncid, nok=0, d, i, j, k, m, err, nels, nslabs;
-    int nstarts;        /* number of different starts */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    double value[MAX_NELS];
-    int reqid, status=NC_NOERR;
+    int i, j, k, err, ncid, nok=0, nslabs, reqid, status;
+    double value[MAX_NELS], ncbuf[MAX_NELS];
+    IntType start[MAX_RANK], index[MAX_RANK], index2[MAX_RANK];
+    IntType count[MAX_RANK], edge[MAX_RANK], mid[MAX_RANK], sstride[MAX_RANK];
+    PTRDType stride[MAX_RANK];
     MPI_Datatype datatype;
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = APIFunc(iput_vars)(BAD_ID, 0, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = APIFunc(iput_vars)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = APIFunc(iput_vars)(BAD_ID, i, NULL, NULL, NULL, value, 1, MPI_DATATYPE_NULL, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        datatype = nc_mpi_type(var_type[i]);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
         }
-        err = ncmpi_iput_vars(BAD_ID, i, start, edge, stride, value, 1, datatype, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = APIFunc(iput_vars)(ncid, i, NULL, NULL, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        err = ncmpi_iput_vars(ncid, BAD_VARID, start, edge, stride, value, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = APIFunc(iput_vars)(ncid, i, start, NULL, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];     /* out of boundary check */
-                err = ncmpi_iput_vars(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
-                IF (err != NC_EINVALCOORDS)
-                    error("expecting bad start, but err = %d", err);
-                ELSE_NOK
-                start[j] = 0;
-                edge[j] = var_shape[i][j] + 1;  /* edge error check */
-                err = ncmpi_iput_vars(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
-                IF (err != NC_EEDGE)
-                    error("expecting bad edge, but err = %d", err);
-                ELSE_NOK
-                edge[j] = 1;
-                stride[j] = 0;  /* strided edge error check */
-                err = ncmpi_iput_vars(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
-                IF (err != NC_ESTRIDE)
-                    error("expecting bad stride, but err = %d", err);
-                ELSE_NOK
-                stride[j] = 1;
-            }
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = APIFunc(iput_vars)(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = APIFunc(iput_vars)(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDG, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;  /* strided edge error check */
+            err = APIFunc(iput_vars)(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
+        }
+        /* Check correct error returned even when nothing to put */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = APIFunc(iput_vars)(ncid, i, start, edge, stride, value, 0, datatype, &reqid);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = APIFunc(iput_vars)(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
         }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* Put 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -1098,7 +1250,8 @@ test_ncmpi_iput_vars(void)
         /* bits of k determine whether to put lower or upper part of dim */
         /* choose random stride from 1 to edge */
         for (k = 0; k < nslabs; k++) {
-            nstarts = 1;
+            IntType nstarts=1; /* number of different starts */
+            int m;
             for (j = 0; j < var_rank[i]; j++) {
                 if ((k >> j) & 1) {
                     start[j] = 0;
@@ -1111,9 +1264,9 @@ test_ncmpi_iput_vars(void)
                 nstarts *= stride[j];
             }
             for (m = 0; m < nstarts; m++) {
+                IntType nels;
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
+                IF (err != 0) error("error in toMixedBase");
                 nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
                     count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
@@ -1129,12 +1282,10 @@ test_ncmpi_iput_vars(void)
                     }
                 }
 */
-                double ncbuf[MAX_NELS];
                 for (j = 0; j < nels; j++) {
+                    int d;
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase");
-                    ELSE_NOK
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
                         index2[d] = index[d] + index2[d] * stride[d];
                     ncbuf[j] = hash2nc(var_type[i], var_rank[i], index2);
@@ -1144,120 +1295,194 @@ test_ncmpi_iput_vars(void)
                 IF (err != NC_NOERR)
                     error("error in dbls2ncs");
 
-                if (var_rank[i] == 0 && i%2 == 0)
-                    err = ncmpi_iput_vars(ncid, i, NULL, NULL, stride, value, nels, datatype, &reqid);
-                else
-                    err = ncmpi_iput_vars(ncid, i, index, count, stride, value, nels, datatype, &reqid);
+                err = APIFunc(iput_vars)(ncid, i, index, count, stride, value, nels, datatype, &reqid);
                 IF (err != NC_NOERR)
-                    error("ncmpi_iput_var1: %s", ncmpi_strerror(err));
+                    EXPECT_ERR(NC_NOERR, err)
                 ELSE_NOK
 
-                err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+                err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
                 IF (err != NC_NOERR)
-                    error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+                    error("wait_all: err=%s", APIFunc(strerror)(err));
+                else IF (status != NC_NOERR)
+                    error("wait_all: status=%s", APIFunc(strerror)(status));
                 ELSE_NOK
             }
         }
     }
 
-    check_vars(ncid);
+    nok += check_vars(ncid, numVars);
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 
-dnl TEST_NC_IPUT_VARS(TYPE)
 dnl
 define(`TEST_NC_IPUT_VARS',dnl
 `dnl
 int
-test_ncmpi_iput_vars_$1(void)
+TestFunc(vars)_$1(VarArgs)
 {
-    int ncid, nok=0;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err;
-    int nels;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    int canConvert;        /* Both text or both numeric */
-    int allInExtRange;        /* all values within external range? */
+    int i, k, err, ncid, cdf_format, nslabs, nok=0, reqid, status;
+    int canConvert;      /* Both text or both numeric */
+    int allInExtRange;   /* all values within external range? */
+    IntType j;
+    IntType start[MAX_RANK], edge[MAX_RANK], mid[MAX_RANK], index[MAX_RANK];
+    IntType index2[MAX_RANK], count[MAX_RANK], sstride[MAX_RANK];
+    PTRDType stride[MAX_RANK];
     $1 value[MAX_NELS];
-    int reqid, status=NC_NOERR;
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = iPutVars($1)(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = iPutVars($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = iPutVars($1)(BAD_ID, i, NULL, NULL, NULL, value, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
         }
-        err = ncmpi_iput_vars_$1(BAD_ID, i, start, edge, stride, value, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = iPutVars($1)(ncid, i, NULL, NULL, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        err = ncmpi_iput_vars_$1(ncid, BAD_VARID, start, edge, stride, value, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = iPutVars($1)(ncid, i, start, NULL, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];     /* out of boundary check */
-                err = ncmpi_iput_vars_$1(ncid, i, start, edge, stride, value, &reqid);
-                if (!canConvert) {
-                    IF (err != NC_ECHAR)
-                        error("conversion: err = %d", err);
-                    ELSE_NOK
-                } else {
-                    IF (err != NC_EINVALCOORDS)
-                        error("expecting bad start, but err = %d", err);
-                    ELSE_NOK
-                    start[j] = 0;
-                    edge[j] = var_shape[i][j] + 1;  /* edge error check */
-                    err = ncmpi_iput_vars_$1(ncid, i, start, edge, stride, value, &reqid);
-                    IF (err != NC_EEDGE)
-                        error("expecting bad edge, but err = %d", err);
-                    ELSE_NOK
-                    edge[j] = 1;
-                    stride[j] = 0;  /* strided edge error check */
-                    err = ncmpi_iput_vars_$1(ncid, i, start, edge, stride, value, &reqid);
-                    IF (err != NC_ESTRIDE)
-                        error("expecting bad stride, but err = %d", err);
-                    ELSE_NOK
-                    stride[j] = 1;
-                }
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j]; /* out of boundary check */
+            err = iPutVars($1)(ncid, i, start, edge, stride, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
+                start[j] = 0;
+                continue;
+            }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = iPutVars($1)(ncid, i, start, edge, stride, value, &reqid);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;  /* strided edge error check */
+            err = iPutVars($1)(ncid, i, start, edge, stride, value, &reqid);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
+        }
+
+        /* Check correct error returned when nothing to put, when edge[*]==0 */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = iPutVars($1)(ncid, i, start, edge, stride, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
+                start[j] = 0;
+                continue;
             }
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1;     /* out of boundary check */
+            err = iPutVars($1)(ncid, i, start, edge, stride, value, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
         }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* Put 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -1268,7 +1493,8 @@ test_ncmpi_iput_vars_$1(void)
         /* bits of k determine whether to put lower or upper part of dim */
         /* choose random stride from 1 to edge */
         for (k = 0; k < nslabs; k++) {
-            nstarts = 1;
+            int m;
+            IntType nstarts = 1;
             for (j = 0; j < var_rank[i]; j++) {
                 if ((k >> j) & 1) {
                     start[j] = 0;
@@ -1281,11 +1507,10 @@ test_ncmpi_iput_vars_$1(void)
                 nstarts *= stride[j];
             }
             for (m = 0; m < nstarts; m++) {
+                IntType nels;
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
-                nels = 1;
-                for (j = 0; j < var_rank[i]; j++) {
+                IF (err != 0) error("error in toMixedBase");
+                for (nels=1, j=0; j < var_rank[i]; j++) {
                     count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
                     nels *= count[j];
                     index[j] += start[j];
@@ -1300,56 +1525,59 @@ test_ncmpi_iput_vars_$1(void)
                 }
 */
                 for (allInExtRange = 1, j = 0; j < nels; j++) {
+                    int d;
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase");
-                    ELSE_NOK
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
                         index2[d] = index[d] + index2[d] * stride[d];
-                    value[j] = hash_$1(var_type[i], var_rank[i], index2, NCT_ITYPE($1));
+                    value[j] = hash_$1(cdf_format, var_type[i], var_rank[i],
+                                       index2, NCT_ITYPE($1));
                     IfCheckTextChar($1, var_type[i])
-                        allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                        allInExtRange &= inRange3(cdf_format, (double)value[j],
+                                                  var_type[i], NCT_ITYPE($1));
                 }
-                if (var_rank[i] == 0 && i%2 == 0)
-                    err = ncmpi_iput_vars_$1(ncid, i, NULL, NULL, stride, value, &reqid);
-                else
-                    err = ncmpi_iput_vars_$1(ncid, i, index, count, stride, value, &reqid);
-                if (err == NC_NOERR || err == NC_ERANGE)
-                    /* NC_ERANGE is not fatal, must continue */
-                    ncmpi_wait_all(ncid, 1, &reqid, &status);
+                err = iPutVars($1)(ncid, i, index, count, stride, value, &reqid);
                 if (canConvert) {
                     if (allInExtRange) {
-                        IF (err != NC_NOERR) 
-                            error("%s", ncmpi_strerror(err));
-                        ELSE_NOK
-                        IF (status != NC_NOERR) 
-                            error("%s", ncmpi_strerror(status));
-                        ELSE_NOK
+                        IF (err != NC_NOERR)
+                            error("%s", APIFunc(strerror)(err));
+                        else {
+                            err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                            IF (err != NC_NOERR)
+                                error("wait_all: err=%s", APIFunc(strerror)(err));
+                            else IF (status != NC_NOERR)
+                                error("wait_all: status=%s", APIFunc(strerror)(status));
+                        }
                     } else {
-                        /* NC_ERANGE is checked at ncmpi_iput_vars_$1() */
                         IF (err != NC_ERANGE)
-                            error("range error: err = %d", err);
-                        ELSE_NOK
+                            EXPECT_ERR(NC_ERANGE, err)
+                        else { /* NC_ERANGE does not invalidate the nonblocking
+                                * request, the request is still posted */
+                            err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                            IF (err != NC_NOERR)
+                                error("wait_all: err=%s", APIFunc(strerror)(err));
+                            else IF (status != NC_NOERR)
+                                error("wait_all: status=%s", APIFunc(strerror)(status));
+                        }
                     }
                 } else {
-                    /* NC_ECHAR is checked at ncmpi_iput_vars_$1() */
-                    IF (nels > 0 && err != NC_ECHAR)
-                        error("wrong type: err = %d", err);
+                    IF (err != NC_ECHAR)
+                        EXPECT_ERR(NC_ECHAR, err)
                     ELSE_NOK
                 }
             }
         }
     }
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    nok += check_vars_$1(scratch);
+    nok += check_vars_$1(scratch, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
@@ -1368,74 +1596,136 @@ TEST_NC_IPUT_VARS(longlong)
 TEST_NC_IPUT_VARS(ulonglong)
 
 int
-test_ncmpi_iput_varm(void)
+TestFunc(varm)(VarArgs)
 {
-    int ncid, nok=0, d, i, j, k, m, err, nels, nslabs;
-    int nstarts;        /* number of different starts */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    MPI_Offset imap[MAX_RANK];
-    double value[MAX_NELS];
-    int reqid, status=NC_NOERR;
+    int i, j, k, err, ncid, nok=0, nslabs, reqid, status;
+    double value[MAX_NELS], ncbuf[MAX_NELS];
+    IntType start[MAX_RANK], index[MAX_RANK], index2[MAX_RANK];
+    IntType count[MAX_RANK], edge[MAX_RANK], mid[MAX_RANK], sstride[MAX_RANK];
+    PTRDType stride[MAX_RANK], imap[MAX_RANK];
     MPI_Datatype datatype;
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = APIFunc(iput_varm)(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = APIFunc(iput_varm)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = APIFunc(iput_varm)(BAD_ID, i, NULL, NULL, NULL, NULL, value, 1, MPI_DATATYPE_NULL, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        datatype = nc_mpi_type(var_type[i]);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
             imap[j] = 1;
         }
-        err = ncmpi_iput_varm(BAD_ID, i, start, edge, stride, imap, value, 1, datatype, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = APIFunc(iput_varm)(ncid, i, NULL, NULL, NULL, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        err = ncmpi_iput_varm(ncid, BAD_VARID, start, edge, stride, imap, value, 1, datatype, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = APIFunc(iput_varm)(ncid, i, start, NULL, NULL, NULL, value, 1, datatype, &reqid);
+        if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];     /* out of boundary check */
-                err = ncmpi_iput_varm(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
-                IF (err != NC_EINVALCOORDS)
-                    error("expecting bad start, but err = %d", err);
-                ELSE_NOK
-                start[j] = 0;
-                edge[j] = var_shape[i][j] + 1;  /* edge error check */
-                err = ncmpi_iput_varm(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
-                IF (err != NC_EEDGE)
-                    error("expecting bad edge, but err = %d", err);
-                ELSE_NOK
-                edge[j] = 1;
-                stride[j] = 0;  /* strided edge error check */
-                err = ncmpi_iput_varm(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
-                IF (err != NC_ESTRIDE)
-                    error("expecting bad stride, but err = %d", err);
-                ELSE_NOK
-                stride[j] = 1;
-            }
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = APIFunc(iput_varm)(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = APIFunc(iput_varm)(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDG, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;  /* strided edge error check */
+            err = APIFunc(iput_varm)(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
         }
+        /* Check correct error returned even when nothing to put */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = APIFunc(iput_varm)(ncid, i, start, edge, stride, imap, value, 0, datatype, &reqid);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = APIFunc(iput_varm)(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* Put 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -1446,7 +1736,8 @@ test_ncmpi_iput_varm(void)
         /* bits of k determine whether to put lower or upper part of dim */
         /* choose random stride from 1 to edge */
         for (k = 0; k < nslabs; k++) {
-            nstarts = 1;
+            IntType nstarts=1; /* number of different starts */
+            int m;
             for (j = 0; j < var_rank[i]; j++) {
                 if ((k >> j) & 1) {
                     start[j] = 0;
@@ -1459,10 +1750,9 @@ test_ncmpi_iput_varm(void)
                 nstarts *= stride[j];
             }
             for (m = 0; m < nstarts; m++) {
+                IntType nels;
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
-                ELSE_NOK
+                IF (err != 0) error("error in toMixedBase");
                 nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
                     count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
@@ -1484,11 +1774,10 @@ test_ncmpi_iput_varm(void)
                     for (; j > 0; j--)
                         imap[j-1] = imap[j] * count[j];
                 }
-                double ncbuf[MAX_NELS];
                 for (j = 0; j < nels; j++) {
+                    int d;
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase");
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
                         index2[d] = index[d] + index2[d] * stride[d];
                     ncbuf[j] = hash2nc(var_type[i], var_rank[i], index2);
@@ -1498,122 +1787,194 @@ test_ncmpi_iput_varm(void)
                 IF (err != NC_NOERR)
                     error("error in dbls2ncs");
 
-                if (var_rank[i] == 0 && i%2 == 0)
-                    err = ncmpi_iput_varm(ncid,i,NULL,NULL,NULL,NULL,value, nels, datatype, &reqid);
-                else
-                    err = ncmpi_iput_varm(ncid,i,index,count,stride,imap,value, nels, datatype,&reqid);
+                err = APIFunc(iput_varm)(ncid, i, index, count, stride, imap, value, nels, datatype, &reqid);
                 IF (err != NC_NOERR)
-                    error("ncmpi_iput_var1: %s", ncmpi_strerror(err));
+                    error("iput_varm: %s", APIFunc(strerror)(err));
                 ELSE_NOK
 
-                err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+                err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
                 IF (err != NC_NOERR)
-                    error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+                    error("wait_all: err=%s", APIFunc(strerror)(err));
+                else IF (status != NC_NOERR)
+                    error("wait_all: status=%s", APIFunc(strerror)(status));
                 ELSE_NOK
             }
         }
     }
 
-    check_vars(ncid);
+    nok += check_vars(ncid, numVars);
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 
-dnl TEST_NC_IPUT_VARM(TYPE)
 dnl
 define(`TEST_NC_IPUT_VARM',dnl
 `dnl
 int
-test_ncmpi_iput_varm_$1(void)
+TestFunc(varm)_$1(VarArgs)
 {
-    int ncid, nok=0;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err;
-    int nels;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    MPI_Offset imap[MAX_RANK];
-    int canConvert;        /* Both text or both numeric */
-    int allInExtRange;        /* all values within external range? */
+    int i, k, err, ncid, cdf_format, nslabs, nok=0, reqid, status;
+    int canConvert;      /* Both text or both numeric */
+    int allInExtRange;   /* all values within external range? */
+    IntType j;
+    IntType start[MAX_RANK], edge[MAX_RANK], mid[MAX_RANK], index[MAX_RANK];
+    IntType index2[MAX_RANK], count[MAX_RANK], sstride[MAX_RANK];
+    PTRDType stride[MAX_RANK], imap[MAX_RANK];
     $1 value[MAX_NELS];
-    int reqid, status=NC_NOERR;
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = iPutVarm($1)(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = iPutVarm($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = iPutVarm($1)(BAD_ID, i, NULL, NULL, NULL, NULL, value, NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
             imap[j] = 1;
         }
-        err = ncmpi_iput_varm_$1(BAD_ID, i, start, edge, stride, imap, value, &reqid);
-        IF (err != NC_EBADID) 
-            error("bad ncid: err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = iPutVarm($1)(ncid, i, NULL, NULL, NULL, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        err = ncmpi_iput_varm_$1(ncid, BAD_VARID, start, edge, stride, imap, value, &reqid);
-        IF (err != NC_ENOTVAR) 
-            error("bad var id: err = %d", err);
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = iPutVarm($1)(ncid, i, start, NULL, NULL, NULL, value, &reqid);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            else {
+                err = APIFunc(wait_all)(ncid, 1, &reqid, NULL);
+                IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+            }
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];     /* out of boundary check */
-                err = ncmpi_iput_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
-                if (!canConvert) {
-                    IF (err != NC_ECHAR)
-                        error("conversion: err = %d", err);
-                    ELSE_NOK
-                } else {
-                    IF (err != NC_EINVALCOORDS)
-                        error("expecting bad start, but err = %d", err);
-                    ELSE_NOK
-                    start[j] = 0;
-                    edge[j] = var_shape[i][j] + 1;  /* edge error check */
-                    err = ncmpi_iput_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
-                    IF (err != NC_EEDGE)
-                        error("expecting bad edge, but err = %d", err);
-                    ELSE_NOK
-                    edge[j] = 1;
-                    stride[j] = 0;  /* strided edge error check */
-                    err = ncmpi_iput_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
-                    IF (err != NC_ESTRIDE)
-                        error("expecting bad stride, but err = %d", err);
-                    ELSE_NOK
-                    stride[j] = 1;
-                }
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j]; /* out of boundary check */
+            err = iPutVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
+                start[j] = 0;
+                continue;
             }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = iPutVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;  /* strided edge error check */
+            err = iPutVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
         }
+        /* Check correct error returned even when nothing to put */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = iPutVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
+                start[j] = 0;
+                continue;
+            }
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1;     /* out of boundary check */
+            err = iPutVarm($1)(ncid, i, start, edge, stride, imap, value, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
         /* Choose a random point dividing each dim into 2 parts */
         /* Put 2^rank (nslabs) slabs so defined */
         nslabs = 1;
@@ -1624,7 +1985,8 @@ test_ncmpi_iput_varm_$1(void)
         /* bits of k determine whether to put lower or upper part of dim */
         /* choose random stride from 1 to edge */
         for (k = 0; k < nslabs; k++) {
-            nstarts = 1;
+            int m;
+            IntType nstarts = 1;
             for (j = 0; j < var_rank[i]; j++) {
                 if ((k >> j) & 1) {
                     start[j] = 0;
@@ -1637,10 +1999,9 @@ test_ncmpi_iput_varm_$1(void)
                 nstarts *= stride[j];
             }
             for (m = 0; m < nstarts; m++) {
+                IntType nels;
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
-                ELSE_NOK
+                IF (err != 0) error("error in toMixedBase");
                 nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
                     count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
@@ -1663,55 +2024,59 @@ test_ncmpi_iput_varm_$1(void)
                         imap[j-1] = imap[j] * count[j];
                 }
                 for (allInExtRange = 1, j = 0; j < nels; j++) {
+                    int d;
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase");
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
                         index2[d] = index[d] + index2[d] * stride[d];
-                    value[j] = hash_$1(var_type[i], var_rank[i], index2, NCT_ITYPE($1));
+                    value[j] = hash_$1(cdf_format, var_type[i], var_rank[i],
+                                       index2, NCT_ITYPE($1));
                     IfCheckTextChar($1, var_type[i])
-                        allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                        allInExtRange &= inRange3(cdf_format, (double)value[j],
+                                                  var_type[i], NCT_ITYPE($1));
                 }
-                if (var_rank[i] == 0 && i%2 == 0)
-                    err = ncmpi_iput_varm_$1(ncid,i,NULL,NULL,NULL,NULL,value, &reqid);
-                else
-                    err = ncmpi_iput_varm_$1(ncid,i,index,count,stride,imap,value,&reqid);
-                if (err == NC_NOERR || err == NC_ERANGE)
-                    /* NC_ERANGE is not fatal, must continue */
-                    ncmpi_wait_all(ncid, 1, &reqid, &status);
+                err = iPutVarm($1)(ncid, i, index, count, stride, imap, value, &reqid);
                 if (canConvert) {
                     if (allInExtRange) {
                         IF (err != NC_NOERR)
-                            error("%s", ncmpi_strerror(err));
-                        ELSE_NOK
-                        IF (status != NC_NOERR)
-                            error("%s", ncmpi_strerror(status));
-                        ELSE_NOK
+                            error("%s", APIFunc(strerror)(err));
+                        else {
+                            err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                            IF (err != NC_NOERR)
+                                error("wait_all: err=%s", APIFunc(strerror)(err));
+                            else IF (status != NC_NOERR)
+                                error("wait_all: status=%s", APIFunc(strerror)(status));
+                        }
                     } else {
-                        /* NC_ERANGE is checked at ncmpi_iput_varm_$1() */
                         IF (err != NC_ERANGE)
-                            error("range error: err = %d", err);
-                        ELSE_NOK
+                            EXPECT_ERR(NC_ERANGE, err)
+                        else { /* NC_ERANGE does not invalidate the nonblocking
+                                * request, the request is still posted */
+                            err = APIFunc(wait_all)(ncid, 1, &reqid, &status);
+                            IF (err != NC_NOERR)
+                                error("wait_all: err=%s", APIFunc(strerror)(err));
+                            else IF (status != NC_NOERR)
+                                error("wait_all: status=%s", APIFunc(strerror)(status));
+                        }
                     }
                 } else {
-                    /* NC_ECHAR is checked at ncmpi_iput_varm_$1() */
-                    IF (nels > 0 && err != NC_ECHAR)
-                        error("wrong type: err = %d", err);
+                    IF (err != NC_ECHAR)
+                        EXPECT_ERR(NC_ECHAR, err)
                     ELSE_NOK
                 }
             }
         }
     }
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    nok += check_vars_$1(scratch);
+    nok += check_vars_$1(scratch, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
@@ -1729,4 +2094,3 @@ TEST_NC_IPUT_VARM(uint)
 TEST_NC_IPUT_VARM(longlong)
 TEST_NC_IPUT_VARM(ulonglong)
 
-
diff --git a/test/nc_test/test_put.m4 b/test/nc_test/test_put.m4
index cb0391b..982e79b 100644
--- a/test/nc_test/test_put.m4
+++ b/test/nc_test/test_put.m4
@@ -1,6 +1,8 @@
 dnl This is m4 source.
 dnl Process using m4 to produce 'C' language file.
 dnl
+dnl This file is supposed to be the same as PnetCDF's test_put.m4
+dnl
 dnl If you see this line, you can ignore the next one.
 /* Do not edit this file. It is produced from the corresponding .m4 source */
 dnl
@@ -8,8 +10,39 @@ dnl
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: test_put.m4 2295 2016-01-06 20:28:09Z wkliao $ */
+/* $Id: test_put.m4 2622 2016-11-15 17:40:08Z wkliao $ */
+
+dnl
+dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
+dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types
+dnl (MPI_Offset vs. size_t), and function name substrings for external data
+dnl types.
+dnl
+
+#include "tests.h"
+
+define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl
+
+define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl
+define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl
+define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_put_$1',`test_nc_put_$1')')dnl
+define(`APIFunc',` ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl
+
+define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, &ncid)', `file_open($1, $2, &ncid)')')dnl
+define(`FileCreate',`ifdef(`PNETCDF',`ncmpi_create(comm, $1, $2, info, &ncid)', `file_create($1, $2, &ncid)')')dnl
+define(`FileDelete',`ifdef(`PNETCDF',`ncmpi_delete($1,$2)',`nc_delete($1)')')dnl
+
+define(`VarArgs',   `ifdef(`PNETCDF',`int numVars',`void')')dnl
+define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts,int numVars',`void')')dnl
 
+define(`PutVar1',`ifdef(`PNETCDF',`ncmpi_put_var1_$1_all',`nc_put_var1_$1')')dnl
+define(`PutVar', `ifdef(`PNETCDF',`ncmpi_put_var_$1_all', `nc_put_var_$1')')dnl
+define(`PutVara',`ifdef(`PNETCDF',`ncmpi_put_vara_$1_all',`nc_put_vara_$1')')dnl
+define(`PutVars',`ifdef(`PNETCDF',`ncmpi_put_vars_$1_all',`nc_put_vars_$1')')dnl
+define(`PutVarm',`ifdef(`PNETCDF',`ncmpi_put_varm_$1_all',`nc_put_varm_$1')')dnl
+define(`PutAtt', `ifdef(`PNETCDF',`ncmpi_put_att_$1',`nc_put_att_$1')')dnl
+define(`GetVar1',`ifdef(`PNETCDF',`ncmpi_get_var1_$1_all',`nc_get_var1_$1')')dnl
+define(`DefVars',`ifdef(`PNETCDF',`def_vars($1,$2)',`def_vars($1)')')dnl
 
 undefine(`index')dnl
 dnl dnl dnl
@@ -37,14 +70,12 @@ define(`CheckText', `ifelse(`$1',`text', , `== (NCT_ITYPE($1) == NCT_TEXT)')')dn
 define(`IfCheckTextChar', `ifelse(`$1',`text', `if ($2 != NC_CHAR)')')dnl
 define(`CheckNumRange',
        `ifelse(`$1',`text', `1',
-               `inRange3($2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
+               `inRange3(cdf_format, (double)$2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
 define(`CheckRange',
        `ifelse(`$1',`text', `0', `($2 >= $1_min && $2 <= $1_max)')')dnl
 define(`CheckRange3',
        `ifelse(`$1',`text', `1',
-               `inRange3($2,$3,NCT_ITYPE($1))')')dnl
-
-#include "tests.h"
+               `inRange3(cdf_format, (double)$2,$3,NCT_ITYPE($1))')')dnl
 
 dnl HASH(TYPE)
 dnl
@@ -53,24 +84,24 @@ define(`HASH',dnl
 /*
  *  ensure hash value within range for internal TYPE
  */
-static
-double
-hash_$1(
-    const nc_type type,
-    const int rank,
-    const MPI_Offset *index,
-    const nct_itype itype)
+$1
+hash_$1(const int         cdf_format,
+        const nc_type     type,
+        const int         rank,
+        const IntType    *index,
+        const nct_itype   itype)
 {
-    const double min = $1_min;
-    const double max = $1_max;
+    double value;
 
-    return MAX(min, MIN(max, hash4( type, rank, index, itype)));
+    value = hash4(cdf_format, type, rank, index, itype);
+    ifelse(`$1',`text',`return (text)value;',`
+    if (value > $1_max) return $1_max;
+    else if (value < $1_min) return $1_min;
+    else return ($1)value;')
 }
 ')dnl
 
-dnl HASH(text)
-#define hash_text hash4
-
+HASH(text)
 HASH(uchar)
 HASH(schar)
 HASH(short)
@@ -88,86 +119,91 @@ dnl CHECK_VARS(TYPE)
 dnl
 define(`CHECK_VARS',dnl
 `dnl
-/* 
+/*
  *  check all vars in file which are (text/numeric) compatible with TYPE
  */
-static
 int
-check_vars_$1(const char *filename)
+check_vars_$1(const char *filename, int numVars)
 {
-    int  ncid;                  /* netCDF id */
-    MPI_Offset index[MAX_RANK];
-    int  err;
-    int  d;
-    int  i;
-    size_t  j;
-    $1 value;
-    nc_type datatype;
-    int ndims;
+    int i, d, err, ncid, cdf_format, ndims;
+    int canConvert;   /* Both text or both numeric */
+    int nok = 0;      /* count of valid comparisons */
     int dimids[MAX_RANK];
+    nc_type datatype;
     char name[NC_MAX_NAME];
-    MPI_Offset length;
-    int canConvert;     /* Both text or both numeric */
-    int nok = 0;      /* count of valid comparisons */
+    IntType j, length, index[MAX_RANK];
     double expect;
+    $1 value;
 
-    err = ncmpi_open(comm, filename, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = FileOpen(filename, NC_NOWRITE);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR) error("inq_format: %s", APIFunc(strerror)(err));
 
     for (i = 0; i < numVars; i++) {
         canConvert = (var_type[i] == NC_CHAR) CheckText($1);
-        if (canConvert) {
-            err = ncmpi_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
+        if (!canConvert) continue;
+
+        err = APIFunc(inq_var)(ncid, i, name, &datatype, &ndims, dimids, NULL);
+        IF (err != NC_NOERR)
+            error("inq_var: %s", APIFunc(strerror)(err));
+        IF (strcmp(name, var_name[i]) != 0)
+            error("Unexpected var_name");
+        IF (datatype != var_type[i])
+            error("Unexpected type");
+        IF (ndims != var_rank[i])
+            error("Unexpected rank");
+        for (j = 0; j < ndims; j++) {
+            err = APIFunc(inq_dim)(ncid, dimids[j], 0, &length);
             IF (err != NC_NOERR)
-                error("ncmpi_inq_var: %s", ncmpi_strerror(err));
-            IF (strcmp(name, var_name[i]) != 0)
-                error("Unexpected var_name");
-            IF (datatype != var_type[i])
-                error("Unexpected type");
-            IF (ndims != var_rank[i])
-                error("Unexpected rank");
-            for (j = 0; j < ndims; j++) {
-                err = ncmpi_inq_dim(ncid, dimids[j], 0, &length);
-                IF (err != NC_NOERR)
-                    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
-                IF (length != var_shape[i][j])
-                    error("Unexpected shape");
-            }
-            for (j = 0; j < var_nels[i]; j++) {
-                err = toMixedBase(j, var_rank[i], var_shape[i], index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase 2");
-                expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1));
-                err = ncmpi_get_var1_$1_all(ncid, i, index, &value);
-                if (CheckNumRange($1, expect, datatype)) {
-                    IF (err != NC_NOERR) {
-                        error("ncmpi_get_var1_$1_all: %s", ncmpi_strerror(err));
-                    } else {
-                        IF (!equal(value,expect,var_type[i],NCT_ITYPE($1))) {
-                            error("Var value read not that expected");
-                            if (verbose) {
-                                error("\n");
-                                error("varid: %d, ", i);
-                                error("var_name: %s, ", var_name[i]);
-                                error("var_type: %s, ", s_nc_type(var_type[i]));
-                                error("index:");
-                                for (d = 0; d < var_rank[i]; d++)
-                                    error(" %d", index[d]);
-                                error(", expect: %g, ", expect);
-                                error("got: %g", (double) value);
-                            }
-                        } else {
-                            ++nok;
+                error("inq_dim: %s", APIFunc(strerror)(err));
+            IF (length != var_shape[i][j])
+                error("Unexpected shape");
+        }
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != 0) error("error in toMixedBase");
+            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
+                           NCT_ITYPE($1));
+            err = GetVar1($1)(ncid, i, index, &value);
+            if (CheckNumRange($1, expect, datatype)) {
+                IF (err != NC_NOERR) {
+                    error("GetVar1($1): %s", APIFunc(strerror)(err));
+                } else {
+                    ifelse(`$1', `uchar', `
+                    /* In put_vars(), PutVara(double)() is used to write
+                     * variables of type NC_BYTE to files. For uchar APIs,
+                     * NC_BYTE variables are treated as unsigned for CDF-1 and 2
+                     * formats. Thus, we skip the equal test for out-of-bound
+                     * values below for uchar APIs.
+                     */
+                    if (cdf_format < NC_FORMAT_CDF5 &&
+                        var_type[i] == NC_BYTE && expect > schar_max)
+                        continue;')
+                    IF (!equal((double)value,expect,var_type[i],NCT_ITYPE($1))){
+                        error("Var value read not that expected");
+                        if (verbose) {
+                            error("\n");
+                            error("varid: %d, ", i);
+                            error("var_name: %s, ", var_name[i]);
+                            error("var_type: %s, ", s_nc_type(var_type[i]));
+                            error("index:");
+                            for (d = 0; d < var_rank[i]; d++)
+                                error(" %d", index[d]);
+                            error(", expect: %g, ", expect);
+                            error("got: %g", (double) value);
                         }
+                    } else {
+                        ++nok;
                     }
                 }
             }
         }
     }
-    err = ncmpi_close(ncid);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
     return nok;
 }
 ')dnl
@@ -186,64 +222,78 @@ CHECK_VARS(longlong)
 CHECK_VARS(ulonglong)
 
 
-dnl CHECK_ATTS(TYPE)         numeric only
+dnl CHECK_ATTS(TYPE)
 dnl
 define(`CHECK_ATTS',dnl
 `dnl
-/* 
- *  check all attributes in file which are (text/numeric) compatible with TYPE
- *  ignore any attributes containing values outside range of TYPE
+/*
+ *  for _text tests, check all attributes in file which are of text type
+ *  Note no NC_ERANGE check for text attributes as text is not convertible to
+ *  any other numerical data types (i.e. NC_ECHAR)
+ *
+ *  for other tests, check all numerical attributes in file against values
+ *  outside range of type $1
  */
-static
 int
-check_atts_$1(int  ncid)
+check_atts_$1(int ncid, int numGatts, int numVars)
 {
-    int  err;
-    int  i;
-    int  j;
-    MPI_Offset  k;
-    $1 value[MAX_NELS];
+    int i, j, cdf_format, err;
+    int canConvert;      /* Both text or both numeric */
+    int nok = 0;         /* count of valid comparisons */
+    IntType k, length;
     nc_type datatype;
-    MPI_Offset length;
-    size_t nInExtRange;  /* number values within external range */
-    size_t nInIntRange;  /* number values within internal range */
-    int canConvert;     /* Both text or both numeric */
-    int nok = 0;      /* count of valid comparisons */
+    IntType nInExtRange;  /* number values within external range */
+    IntType nInIntRange;  /* number values within internal range */
     double expect[MAX_NELS];
+    $1 value[MAX_NELS];
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
 
     for (i = -1; i < numVars; i++) {
         for (j = 0; j < NATTS(i); j++) {
             canConvert = (ATT_TYPE(i,j) == NC_CHAR) CheckText($1);
             if (!canConvert) continue;
 
-            err = ncmpi_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
+            err = APIFunc(inq_att)(ncid, i, ATT_NAME(i,j), &datatype, &length);
             IF (err != NC_NOERR)
-                error("ncmpi_inq_att: %s", ncmpi_strerror(err));
+                error("inq_att: %s", APIFunc(strerror)(err));
             IF (datatype != ATT_TYPE(i,j))
-            error("ncmpi_inq_att: unexpected type");
+                error("inq_att: unexpected type");
             IF (length != ATT_LEN(i,j))
-                error("ncmpi_inq_att: unexpected length");
+                error("inq_att: unexpected length");
             assert(length <= MAX_NELS);
             nInIntRange = nInExtRange = 0;
             for (k = 0; k < length; k++) {
-                expect[k] = hash4( datatype, -1, &k, NCT_ITYPE($1));
-                if (inRange3(expect[k], datatype, NCT_ITYPE($1))) {
+                expect[k] = hash4(cdf_format, datatype, -1, &k, NCT_ITYPE($1));
+                if (inRange3(cdf_format, expect[k], datatype, NCT_ITYPE($1))) {
                     ++nInExtRange;
                     if (CheckRange($1, expect[k]))
                         ++nInIntRange;
                 }
             }
-            err = ncmpi_get_att_$1(ncid, i, ATT_NAME(i,j), value);
+            err = APIFunc(get_att_$1)(ncid, i, ATT_NAME(i,j), value);
             if (nInExtRange == length && nInIntRange == length) {
                 IF (err != NC_NOERR)
-                    error("%s", ncmpi_strerror(err));
+                    error("%s", APIFunc(strerror)(err));
             } else {
                 IF (err != NC_NOERR && err != NC_ERANGE)
-                    error("OK or Range error: err = %d", err);
+                    EXPECT_ERR(NC_NOERR or NC_ERANGE, err)
             }
             for (k = 0; k < length; k++) {
                 if (CheckNumRange($1, expect[k], datatype)) {
-                    IF (!equal(value[k],expect[k],datatype,NCT_ITYPE($1))) {
+                    ifelse(`$1', `uchar', `
+                    /* In put_vars(), PutVara(double)() is used to write
+                     * variables of type NC_BYTE to files. For uchar APIs,
+                     * NC_BYTE variables are treated as unsigned for CDF-1 and 2
+                     * formats. Thus, we skip the equal test for out-of-bound
+                     * values below for uchar APIs.
+                     */
+                    if (cdf_format < NC_FORMAT_CDF5 &&
+                        ATT_TYPE(i,j) == NC_BYTE && expect[k] > schar_max)
+                        continue;')
+                    IF (!equal((double)value[k],expect[k],datatype,NCT_ITYPE($1))) {
                         error("att. value read not that expected");
                         if (verbose) {
                             error("\n");
@@ -258,8 +308,8 @@ check_atts_$1(int  ncid)
                         nok++;
                     }
                 }
-            }                                               
-        }                                               
+            }
+        }
     }
     return nok;
 }
@@ -284,89 +334,128 @@ dnl
 define(`TEST_NC_PUT_VAR1',dnl
 `dnl
 int
-test_ncmpi_put_var1_$1(void)
+TestFunc(var1)_$1(VarArgs)
 {
-    int ncid, nok=0;
-    int i;
-    int j;
-    int err;
-    MPI_Offset index[MAX_RANK];
-    int canConvert;        /* Both text or both numeric */
-    $1 value = 5;        /* any value would do - only for error cases */
+    int i, err, ncid, cdf_format, nok=0;
+    int canConvert;      /* Both text or both numeric */
+    IntType j, index[MAX_RANK];
+    $1 value[1];
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = PutVar1($1)(BAD_ID, 0, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutVar1($1)(ncid, BAD_VARID, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
-        for (j = 0; j < var_rank[i]; j++)
-            index[j] = 0;
-        err = ncmpi_put_var1_$1_all(BAD_ID, i, index, &value);
-        IF (err != NC_EBADID) 
-            error("expecting NC_EBADID (bad ncid), but err = %s", nc_err_code_name(err));
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = PutVar1($1)(BAD_ID, i, NULL, value);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
         ELSE_NOK
-        err = ncmpi_put_var1_$1_all(ncid, BAD_VARID, index, &value);
-        IF (err != NC_ENOTVAR) 
-            error("expecting NC_ENOTVAR (bad var id), but err = %s", nc_err_code_name(err));
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = PutVar1($1)(ncid, i, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS */
+        for (j = 0; j < var_rank[i]; j++) index[j] = 0;
+
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                index[j] = var_shape[i][j];     /* out of boundary check */
-                err = ncmpi_put_var1_$1_all(ncid, i, index, &value);
-                IF (canConvert && err != NC_EINVALCOORDS)
-                    error("expecting NC_EINVALCOORDS (bad index), but err = %s", nc_err_code_name(err));
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            index[j] = var_shape[i][j];     /* out of boundary check */
+            err = PutVar1($1)(ncid, i, index, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
                 index[j] = 0;
+                continue;
             }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            index[j] = 0;
         }
+
         for (j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR) 
-                error("error in toMixedBase 1");
-            value = hash_$1( var_type[i], var_rank[i], index, NCT_ITYPE($1));
-            if (var_rank[i] == 0 && i%2 == 0)
-                err = ncmpi_put_var1_$1_all(ncid, i, NULL, &value);
-            else
-                err = ncmpi_put_var1_$1_all(ncid, i, index, &value);
+            IF (err != 0) error("error in toMixedBase");
+            value[0] = hash_$1(cdf_format, var_type[i], var_rank[i], index,
+                               NCT_ITYPE($1));
+            err = PutVar1($1)(ncid, i, index, value);
             if (canConvert) {
-                if (CheckRange3($1, value, var_type[i])) {
+                if (CheckRange3($1, value[0], var_type[i])) {
                     IF (err != NC_NOERR)
-                        error("%s", ncmpi_strerror(err));
+                        error("%s", APIFunc(strerror)(err));
                     ELSE_NOK
                 } else {
                     IF (err != NC_ERANGE) {
-                        error("Range error: err = %d", err);
+                        EXPECT_ERR(NC_ERANGE, err)
                         error("\n\t\tfor type %s value %.17e %ld",
                                 s_nc_type(var_type[i]),
-                                (double)value, (long)value);
+                                (double)value[0], (long)value[0]);
                     }
                     ELSE_NOK
                 }
             } else {
                 IF (err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
             }
         }
     }
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    nok += check_vars_$1(scratch);
+    nok += check_vars_$1(scratch, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
@@ -390,137 +479,140 @@ dnl
 define(`TEST_NC_PUT_VAR',dnl
 `dnl
 int
-test_ncmpi_put_var_$1(void)
+TestFunc(var)_$1(VarArgs)
 {
-    int ncid, nok=0;
-    int varid;
-    int i;
-    int j;
-    int err;
-    int nels;
-    MPI_Offset index[MAX_RANK];
+    int i, err, ncid, varid, cdf_format, nok=0;
     int canConvert;        /* Both text or both numeric */
-    int allInExtRange;        /* all values within external range? */
+    int allInExtRange;     /* all values within external range? */
+    IntType j, index[MAX_RANK];
     $1 value[MAX_NELS];
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = PutVar($1)(BAD_ID, 0, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutVar($1)(ncid, BAD_VARID, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
-        err = ncmpi_put_var_$1_all(BAD_ID, i, value);
-        IF (err != NC_EBADID) 
-            error("expecting bad ncid, but err = %d", err);
-        ELSE_NOK
-        err = ncmpi_put_var_$1_all(ncid, BAD_VARID, value);
-        IF (err != NC_ENOTVAR) 
-            error("expecting bad var id, but err = %d", err);
+
+        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = PutVar($1)(BAD_ID, i, value);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
         ELSE_NOK
 
-        nels = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            nels *= var_shape[i][j];
-        }
-        for (allInExtRange = 1, j = 0; j < nels; j++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
+        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
             err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR) 
-                error("error in toMixedBase 1");
-            value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+            IF (err != 0) error("error in toMixedBase");
+            value[j]= hash_$1(cdf_format,var_type[i], var_rank[i], index,
+                              NCT_ITYPE($1));
             IfCheckTextChar($1, var_type[i])
-                allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                allInExtRange &= inRange3(cdf_format, (double)value[j],
+                                          var_type[i], NCT_ITYPE($1));
         }
-        err = ncmpi_put_var_$1_all(ncid, i, value);
+        err = PutVar($1)(ncid, i, value);
         if (canConvert) {
             if (allInExtRange) {
-                IF (err != NC_NOERR) 
-                    error("%s", ncmpi_strerror(err));
+                IF (err != NC_NOERR)
+                    error("%s", APIFunc(strerror)(err));
                 ELSE_NOK
             } else {
-                IF (err != NC_ERANGE && var_dimid[i][0] != RECDIM)
-                    error("expecting range error, but err = %d", err);
+                IF (err != NC_ERANGE)
+                    EXPECT_ERR(NC_ERANGE, err)
                 ELSE_NOK
             }
         } else { /* should flag wrong type even if nothing to write */
-            IF (nels > 0 && err != NC_ECHAR)
-                error("wrong type: err = %d", err);
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
             ELSE_NOK
         }
     }
 
-    /* Preceeding has written nothing for record variables, now try */
+    /* Preceding has written nothing for record variables, now try */
     /* again with more than 0 records */
 
     /* Write record number NRECS to force writing of preceding records */
     /* Assumes variable cr is char vector with UNLIMITED dimension */
-    err = ncmpi_inq_varid(ncid, "cr", &varid);
+    err = APIFunc(inq_varid)(ncid, "cr", &varid);
     IF (err != NC_NOERR)
-        error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+        error("inq_varid: %s", APIFunc(strerror)(err));
     index[0] = NRECS-1;
-    err = ncmpi_put_var1_text_all(ncid, varid, index, "x");
+    err = PutVar1(text)(ncid, varid, index, "x");
     IF (err != NC_NOERR)
-        error("ncmpi_put_var1_text_all: %s", ncmpi_strerror(err));
+        error("put_var1_text: %s", APIFunc(strerror)(err));
 
     for (i = 0; i < numVars; i++) {
-        if (var_dimid[i][0] == RECDIM) {  /* only test record variables here */
-            canConvert = (var_type[i] == NC_CHAR) CheckText($1);
-            assert(var_rank[i] <= MAX_RANK);
-            assert(var_nels[i] <= MAX_NELS);
-            err = ncmpi_put_var_$1_all(BAD_ID, i, value);
-            IF (err != NC_EBADID) 
-                error("expecting bad ncid, but err = %d", err);
-            ELSE_NOK
+        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */
 
-            nels = 1;
-            for (j = 0; j < var_rank[i]; j++) {
-                nels *= var_shape[i][j];
-            }
-            for (allInExtRange = 1, j = 0; j < nels; j++) {
-                err = toMixedBase(j, var_rank[i], var_shape[i], index);
-                IF (err != NC_NOERR) 
-                    error("error in toMixedBase 1");
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
+        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != 0) error("error in toMixedBase");
+            value[j]= hash_$1(cdf_format,var_type[i], var_rank[i], index,
+                              NCT_ITYPE($1));
+            IfCheckTextChar($1, var_type[i])
+                allInExtRange &= inRange3(cdf_format, (double)value[j],
+                                          var_type[i], NCT_ITYPE($1));
+        }
+        err = PutVar($1)(ncid, i, value);
+        if (canConvert) {
+            if (allInExtRange) {
+                IF (err != NC_NOERR)
+                    error("%s", APIFunc(strerror)(err));
                 ELSE_NOK
-                value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
-                IfCheckTextChar($1, var_type[i])
-                    allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
-            }
-            err = ncmpi_put_var_$1_all(ncid, i, value);
-            if (canConvert) {
-                if (allInExtRange) {
-                    IF (err != NC_NOERR) 
-                        error("%s", ncmpi_strerror(err));
-                    ELSE_NOK
-                } else {
-                    IF (err != NC_ERANGE)
-                        error("expecting range error, but err = %d", err);
-                    ELSE_NOK
-                }
             } else {
-                IF (nels > 0 && err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                IF (err != NC_ERANGE)
+                    EXPECT_ERR(NC_ERANGE, err)
                 ELSE_NOK
             }
+        } else {
+            IF (err != NC_ECHAR)
+                EXPECT_ERR(NC_ECHAR, err)
+            ELSE_NOK
         }
     }
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    nok += check_vars_$1(scratch);
+    nok += check_vars_$1(scratch, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
@@ -544,110 +636,146 @@ dnl
 define(`TEST_NC_PUT_VARA',dnl
 `dnl
 int
-test_ncmpi_put_vara_$1(void)
+TestFunc(vara)_$1(VarArgs)
 {
-    int ncid, nok=0;
-    int d;
-    int i;
-    int j;
-    int k;
-    int err;
-    int nslabs;
-    int nels;
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
+    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
     int canConvert;        /* Both text or both numeric */
-    int allInExtRange;        /* all values within external range? */
+    int allInExtRange;     /* all values within external range? */
+    IntType j, nels;
+    IntType start[MAX_RANK], edge[MAX_RANK];
+    IntType mid[MAX_RANK], index[MAX_RANK];
     $1 value[MAX_NELS];
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = PutVara($1)(BAD_ID, 0, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutVara($1)(ncid, BAD_VARID, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
-    value[0] = 0;
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5; /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = PutVara($1)(BAD_ID, i, NULL, NULL, value);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
         }
-        err = ncmpi_put_vara_$1_all(BAD_ID, i, start, edge, value);
-        IF (err != NC_EBADID) 
-            error("expecting bad ncid, but err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = PutVara($1)(ncid, i, NULL, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        err = ncmpi_put_vara_$1_all(ncid, BAD_VARID, start, edge, value);
-        IF (err != NC_ENOTVAR) 
-            error("expecting bad var id, but err = %d", err);
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = PutVara($1)(ncid, i, start, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];
-                err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value);
-                IF (canConvert && err != NC_EINVALCOORDS)
-                    error("expecting bad start, but err = %d", err);
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = PutVara($1)(ncid, i, start, edge, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
                 start[j] = 0;
-                edge[j] = var_shape[i][j] + 1;
-                err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value);
-                IF (canConvert && err != NC_EEDGE)
-                    error("expecting bad edge, but err = %d", err);
-                ELSE_NOK
-                edge[j] = 1;
+                continue;
             }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;
+            err = PutVara($1)(ncid, i, start, edge, value);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDG, err)
+            ELSE_NOK
+            edge[j] = 1;
         }
 
-        /* Check correct error returned even when nothing to put */
-        for (j = 0; j < var_rank[i]; j++) {
-            edge[j] = 0;
-        }
-        err = ncmpi_put_vara_$1_all(BAD_ID, i, start, edge, value);
-        IF (err != NC_EBADID) 
-            error("expecting bad ncid, but err = %d", err);
-        ELSE_NOK
-        err = ncmpi_put_vara_$1_all(ncid, BAD_VARID, start, edge, value);
-        IF (err != NC_ENOTVAR) 
-            error("expecting bad var id, but err = %d", err);
-        ELSE_NOK
+        /* Check correct error returned when nothing to put, when edge[*]==0 */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];
-                err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value);
-                IF (canConvert && err != NC_EINVALCOORDS)
-                    error("expecting bad start, but err = %d", err);
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = PutVara($1)(ncid, i, start, edge, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
                 start[j] = 0;
+                continue;
             }
-        }
-
-/* wkliao: this test below of put_vara is redundant and incorrectly uses the
-           value[] set from the previously iteration. There is no such test
-           in put_vars and put_varm.
-
-        err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value);
-        if (canConvert) {
-            IF (err != NC_NOERR)
-                error("%s", ncmpi_strerror(err));
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
             ELSE_NOK
-        } else {
-            IF (err != NC_ECHAR)
-                error("wrong type: err = %d", err);
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = PutVara($1)(ncid, i, start, edge, value);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
             ELSE_NOK
+            start[j] = 0;
         }
-*/
-        for (j = 0; j < var_rank[i]; j++) {
-            edge[j] = 1;
-        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
 
         /* Choose a random point dividing each dim into 2 parts */
         /* Put 2^rank (nslabs) slabs so defined */
@@ -669,47 +797,46 @@ test_ncmpi_put_vara_$1(void)
                 }
                 nels *= edge[j];
             }
+
             for (allInExtRange = 1, j = 0; j < nels; j++) {
                 err = toMixedBase(j, var_rank[i], edge, index);
-                IF (err != NC_NOERR) 
-                    error("error in toMixedBase 1");
-                for (d = 0; d < var_rank[i]; d++) 
+                IF (err != 0) error("error in toMixedBase");
+                for (d = 0; d < var_rank[i]; d++)
                     index[d] += start[d];
-                value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+                value[j]= hash_$1(cdf_format,var_type[i], var_rank[i], index,
+                                  NCT_ITYPE($1));
                 IfCheckTextChar($1, var_type[i])
-                    allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                    allInExtRange &= inRange3(cdf_format, (double)value[j],
+                                              var_type[i], NCT_ITYPE($1));
             }
-            if (var_rank[i] == 0 && i%2 == 0)
-                err = ncmpi_put_vara_$1_all(ncid, i, NULL, NULL, value);
-            else
-                err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value);
+            err = PutVara($1)(ncid, i, start, edge, value);
             if (canConvert) {
                 if (allInExtRange) {
-                    IF (err != NC_NOERR) 
-                        error("%s", ncmpi_strerror(err));
+                    IF (err != NC_NOERR)
+                        EXPECT_ERR(NC_NOERR, err)
                     ELSE_NOK
                 } else {
                     IF (err != NC_ERANGE)
-                        error("expecting range error, but err = %d", err);
+                        EXPECT_ERR(NC_ERANGE, err)
                     ELSE_NOK
                 }
             } else {
-                IF (nels > 0 && err != NC_ECHAR)
-                    error("wrong type: err = %d", err);
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
                 ELSE_NOK
             }
         }
     }
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    nok += check_vars_$1(scratch);
+    nok += check_vars_$1(scratch, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
@@ -733,86 +860,154 @@ dnl
 define(`TEST_NC_PUT_VARS',dnl
 `dnl
 int
-test_ncmpi_put_vars_$1(void)
+TestFunc(vars)_$1(VarArgs)
 {
-    int ncid, nok=0;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err;
-    int nels;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    int canConvert;        /* Both text or both numeric */
-    int allInExtRange;        /* all values within external range? */
+    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
+    int canConvert;     /* Both text or both numeric */
+    int allInExtRange;  /* all values within external range? */
+    IntType j, m, nels;
+    IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
+    IntType index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
+    IntType sstride[MAX_RANK];
+    PTRDType nstarts;   /* number of different starts */
+    PTRDType stride[MAX_RANK];
     $1 value[MAX_NELS];
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = PutVars($1)(BAD_ID, 0, NULL, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutVars($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5; /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = PutVars($1)(BAD_ID, i, NULL, NULL, NULL, value);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
         }
-        err = ncmpi_put_vars_$1_all(BAD_ID, i, start, edge, stride, value);
-        IF (err != NC_EBADID) 
-            error("expecting bad ncid, but err = %d", err);
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = PutVars($1)(ncid, i, NULL, NULL, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        err = ncmpi_put_vars_$1_all(ncid, BAD_VARID, start, edge, stride, value);
-        IF (err != NC_ENOTVAR) 
-            error("expecting bad var id, but err = %d", err);
+        
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = PutVars($1)(ncid, i, start, NULL, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];
-                err = ncmpi_put_vars_$1_all(ncid, i, start, edge, stride, value);
-                if (!canConvert) {
-                    IF (err != NC_ECHAR)
-                        error("conversion: err = %d", err);
-                    ELSE_NOK
-                } else {
-                    IF (err != NC_EINVALCOORDS)
-                        error("expecting bad start, but err = %d", err);
-                    ELSE_NOK
-                    start[j] = 0;
-                    edge[j] = var_shape[i][j] + 1;
-                    err = ncmpi_put_vars_$1_all(ncid, i, start, edge, stride, value);
-                    IF (err != NC_EEDGE)
-                        error("expecting bad edge, but err = %d", err);
-                    ELSE_NOK
-                    edge[j] = 1;
-                    stride[j] = 0;
-                    err = ncmpi_put_vars_$1_all(ncid, i, start, edge, stride, value);
-                    IF (err != NC_ESTRIDE)
-                        error("expecting bad stride, but err = %d", err);
-                    ELSE_NOK
-                    stride[j] = 1;
-                }
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];   /* out of boundary check */
+            err = PutVars($1)(ncid, i, start, edge, stride, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
+                start[j] = 0;
+                continue;
+            }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;
+            err = PutVars($1)(ncid, i, start, edge, stride, value);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;
+            err = PutVars($1)(ncid, i, start, edge, stride, value);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
+        }
+        /* Check correct error returned even when nothing to put */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = PutVars($1)(ncid, i, start, edge, stride, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
+                start[j] = 0;
+                continue;
             }
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = PutVars($1)(ncid, i, start, edge, stride, value);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
         }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
 
         /* Choose a random point dividing each dim into 2 parts */
         /* Put 2^rank (nslabs) slabs so defined */
@@ -833,16 +1028,16 @@ test_ncmpi_put_vars_$1(void)
                     start[j] = mid[j];
                     edge[j] = var_shape[i][j] - mid[j];
                 }
-                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                stride[j] = (PTRDType)sstride[j];
                 nstarts *= stride[j];
             }
             for (m = 0; m < nstarts; m++) {
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
+                IF (err != 0) error("error in toMixedBase");
                 nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
-                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j];
                     nels *= count[j];
                     index[j] += start[j];
                 }
@@ -850,54 +1045,51 @@ test_ncmpi_put_vars_$1(void)
 /* TODO
                 if ( roll(2) ) {
                     for (j = 0; j < var_rank[i]; j++) {
-                        index[j] += (count[j] - 1) * stride[j];
+                        index[j] += (count[j] - 1) * (IntType)stride[j];
                         stride[j] = -stride[j];
                     }
                 }
 */
                 for (allInExtRange = 1, j = 0; j < nels; j++) {
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase");
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
-                        index2[d] = index[d] + index2[d] * stride[d];
-                    value[j] = hash_$1(var_type[i], var_rank[i], index2, 
-                        NCT_ITYPE($1));
+                        index2[d] = index[d] + index2[d] * (IntType)stride[d];
+                    value[j] = hash_$1(cdf_format,var_type[i], var_rank[i],
+                                       index2, NCT_ITYPE($1));
                     IfCheckTextChar($1, var_type[i])
-                        allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                        allInExtRange &= inRange3(cdf_format, (double)value[j],
+                                                  var_type[i], NCT_ITYPE($1));
                 }
-                if (var_rank[i] == 0 && i%2 == 0)
-                    err = ncmpi_put_vars_$1_all(ncid, i, NULL, NULL, stride, value);
-                else
-                    err = ncmpi_put_vars_$1_all(ncid, i, index, count, stride, value);
+                err = PutVars($1)(ncid, i, index, count, stride, value);
                 if (canConvert) {
                     if (allInExtRange) {
-                        IF (err != NC_NOERR) 
-                            error("%s", ncmpi_strerror(err));
+                        IF (err != NC_NOERR)
+                            error("%s", APIFunc(strerror)(err));
                         ELSE_NOK
                     } else {
                         IF (err != NC_ERANGE)
-                            error("expecting range error, but err = %d", err);
+                            EXPECT_ERR(NC_ERANGE, err)
                         ELSE_NOK
                     }
                 } else {
-                    IF (nels > 0 && err != NC_ECHAR)
-                        error("wrong type: err = %d", err);
+                    IF (err != NC_ECHAR)
+                        EXPECT_ERR(NC_ECHAR, err)
                     ELSE_NOK
                 }
             }
         }
     }
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    nok += check_vars_$1(scratch);
+    nok += check_vars_$1(scratch, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
@@ -921,88 +1113,156 @@ dnl
 define(`TEST_NC_PUT_VARM',dnl
 `dnl
 int
-test_ncmpi_put_varm_$1(void)
+TestFunc(varm)_$1(VarArgs)
 {
-    int ncid, nok=0;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err;
-    int nels;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    MPI_Offset imap[MAX_RANK];
-    int canConvert;        /* Both text or both numeric */
-    int allInExtRange;        /* all values within external range? */
+    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
+    int canConvert;     /* Both text or both numeric */
+    int allInExtRange;  /* all values within external range? */
+    IntType j, m, nels;
+    IntType start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
+    IntType index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
+    IntType sstride[MAX_RANK];
+    PTRDType nstarts;   /* number of different starts */
+    PTRDType stride[MAX_RANK], imap[MAX_RANK];
     $1 value[MAX_NELS];
 
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_CLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
+    DefVars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = PutVarm($1)(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutVarm($1)(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = 0; i < numVars; i++) {
-        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
         assert(var_rank[i] <= MAX_RANK);
         assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5; /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = PutVarm($1)(BAD_ID, i, NULL, NULL, NULL, NULL, value);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+
         for (j = 0; j < var_rank[i]; j++) {
             start[j] = 0;
             edge[j] = 1;
             stride[j] = 1;
             imap[j] = 1;
         }
-        err = ncmpi_put_varm_$1_all(BAD_ID, i, start, edge, stride, imap, value);
-        IF (err != NC_EBADID) 
-            error("expecting bad ncid, but err = %d", err);
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = PutVarm($1)(ncid, i, NULL, NULL, NULL, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
         ELSE_NOK
-        err = ncmpi_put_varm_$1_all(ncid, BAD_VARID, start, edge, stride, imap, value);
-        IF (err != NC_ENOTVAR) 
-            error("expecting bad var id, but err = %d", err);
+        
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = PutVarm($1)(ncid, i, start, NULL, NULL, NULL, value);
+        if (!canConvert) {
+            IF (err != NC_ECHAR) EXPECT_ERR(NC_ECHAR, err)
+        }
+        else if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
         ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
         for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {                /* skip record dim */
-                start[j] = var_shape[i][j];
-                err = ncmpi_put_varm_$1_all(ncid, i, start, edge, stride, imap, value);
-                if (!canConvert) {
-                    IF (err != NC_ECHAR)
-                        error("conversion: err = %d", err);
-                    ELSE_NOK
-                } else {
-                    IF (err != NC_EINVALCOORDS)
-                        error("expecting bad start, but err = %d", err);
-                    ELSE_NOK
-                    start[j] = 0;
-                    edge[j] = var_shape[i][j] + 1;
-                    err = ncmpi_put_varm_$1_all(ncid, i, start, edge, stride, imap, value);
-                    IF (err != NC_EEDGE)
-                        error("expecting bad edge, but err = %d", err);
-                    ELSE_NOK
-                    edge[j] = 1;
-                    stride[j] = 0;
-                    err = ncmpi_put_varm_$1_all(ncid, i, start, edge, stride, imap, value);
-                    IF (err != NC_ESTRIDE)
-                        error("expecting bad stride, but err = %d", err);
-                    ELSE_NOK
-                    stride[j] = 1;
-                }
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];   /* out of boundary check */
+            err = PutVarm($1)(ncid, i, start, edge, stride, imap, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
+                start[j] = 0;
+                continue;
             }
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;
+            err = PutVarm($1)(ncid, i, start, edge, stride, imap, value);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;
+            err = PutVarm($1)(ncid, i, start, edge, stride, imap, value);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
         }
+        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = PutVarm($1)(ncid, i, start, edge, stride, imap, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    EXPECT_ERR(NC_ECHAR, err)
+                ELSE_NOK
+                start[j] = 0;
+                continue;
+            }
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = PutVarm($1)(ncid, i, start, edge, stride, imap, value);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
 
         /* Choose a random point dividing each dim into 2 parts */
         /* Put 2^rank (nslabs) slabs so defined */
@@ -1023,16 +1283,16 @@ test_ncmpi_put_varm_$1(void)
                     start[j] = mid[j];
                     edge[j] = var_shape[i][j] - mid[j];
                 }
-                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                stride[j] = (PTRDType)sstride[j];
                 nstarts *= stride[j];
             }
             for (m = 0; m < nstarts; m++) {
                 err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
+                IF (err != 0) error("error in toMixedBase");
                 nels = 1;
                 for (j = 0; j < var_rank[i]; j++) {
-                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j];
                     nels *= count[j];
                     index[j] += start[j];
                 }
@@ -1040,60 +1300,57 @@ test_ncmpi_put_varm_$1(void)
 /* TODO
                 if ( roll(2) ) {
                     for (j = 0; j < var_rank[i]; j++) {
-                        index[j] += (count[j] - 1) * stride[j];
+                        index[j] += (count[j] - 1) * (IntType)stride[j];
                         stride[j] = -stride[j];
                     }
                 }
 */
                 if (var_rank[i] > 0) {
-                    j = var_rank[i] - 1;
-                    imap[j] = 1;
-                    for (; j > 0; j--)
-                        imap[j-1] = imap[j] * count[j];
+                    int jj = var_rank[i] - 1;
+                    imap[jj] = 1;
+                    for (; jj > 0; jj--)
+                        imap[jj-1] = imap[jj] * (PTRDType)count[jj];
                 }
                 for (allInExtRange = 1, j = 0; j < nels; j++) {
                     err = toMixedBase(j, var_rank[i], count, index2);
-                    IF (err != NC_NOERR)
-                        error("error in toMixedBase");
+                    IF (err != 0) error("error in toMixedBase");
                     for (d = 0; d < var_rank[i]; d++)
-                        index2[d] = index[d] + index2[d] * stride[d];
-                    value[j] = hash_$1(var_type[i], var_rank[i], index2,
-                        NCT_ITYPE($1));
+                        index2[d] = index[d] + index2[d] * (IntType)stride[d];
+                    value[j] = hash_$1(cdf_format,var_type[i], var_rank[i],
+                                       index2, NCT_ITYPE($1));
                     IfCheckTextChar($1, var_type[i])
-                        allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                        allInExtRange &= inRange3(cdf_format, (double)value[j],
+                                                  var_type[i], NCT_ITYPE($1));
                 }
-                if (var_rank[i] == 0 && i%2 == 0)
-                    err = ncmpi_put_varm_$1_all(ncid,i,NULL,NULL,NULL,NULL,value);
-                else
-                    err = ncmpi_put_varm_$1_all(ncid,i,index,count,stride,imap,value);
+                err = PutVarm($1)(ncid,i,index,count,stride,imap,value);
                 if (canConvert) {
                     if (allInExtRange) {
                         IF (err != NC_NOERR)
-                            error("%s", ncmpi_strerror(err));
+                            error("%s", APIFunc(strerror)(err));
                         ELSE_NOK
                     } else {
                         IF (err != NC_ERANGE)
-                            error("expecting range error, but err = %d", err);
+                            EXPECT_ERR(NC_ERANGE, err)
                         ELSE_NOK
                     }
                 } else {
-                    IF (nels > 0 && err != NC_ECHAR)
-                        error("wrong type: err = %d", err);
+                    IF (err != NC_ECHAR)
+                        EXPECT_ERR(NC_ECHAR, err)
                     ELSE_NOK
                 }
             }
         }
     }
 
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
 
-    nok += check_vars_$1(scratch);
+    nok += check_vars_$1(scratch, numVars);
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
@@ -1113,66 +1370,71 @@ TEST_NC_PUT_VARM(ulonglong)
 
 
 int
-test_ncmpi_put_att_text(void)
+TestFunc(att)_text(AttVarArgs)
 {
-    int ncid, nok=0;
-    int i;
-    int j;
-    MPI_Offset k;
-    int err;
+    int i, j, err, ncid, nok=0;
+    IntType k;
     text value[MAX_NELS];
 
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_NOCLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
     def_dims(ncid);
-    def_vars(ncid);
+    DefVars(ncid, numVars);
+
+    /* check if can detect a bad file ID */
+    err = PutAtt(text)(BAD_ID, 0, NULL, 0, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutAtt(text)(ncid, BAD_VARID, NULL, 0, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     {
         const char *const tval = "value for bad name";
-        const size_t tval_len = strlen(tval);
-        
-        err = ncmpi_put_att_text(ncid, 0, "", tval_len, tval);
+        const IntType tval_len = (IntType)strlen(tval);
+
+        err = PutAtt(text)(ncid, 0, "", tval_len, tval);
         IF (err != NC_EBADNAME)
-           error("should be NC_EBADNAME: err = %d", err);
+           EXPECT_ERR(NC_EBADNAME, err)
         ELSE_NOK
     }
     for (i = -1; i < numVars; i++) {
         for (j = 0; j < NATTS(i); j++) {
             if (ATT_TYPE(i,j) == NC_CHAR) {
                 assert(ATT_LEN(i,j) <= MAX_NELS);
-                err = ncmpi_put_att_text(BAD_ID, i, ATT_NAME(i,j), ATT_LEN(i,j), 
-                    value);
-                IF (err != NC_EBADID)
-                    error("expecting bad ncid, but err = %d", err);
-                ELSE_NOK
-                err = ncmpi_put_att_text(ncid, BAD_VARID, ATT_NAME(i,j), 
-                    ATT_LEN(i,j), value);
+
+                err = PutAtt(text)(ncid, BAD_VARID, ATT_NAME(i,j), ATT_LEN(i,j), value);
                 IF (err != NC_ENOTVAR)
-                    error("expecting bad var id, but err = %d", err);
+                    EXPECT_ERR(NC_ENOTVAR, err)
                 ELSE_NOK
+
                 for (k = 0; k < ATT_LEN(i,j); k++) {
-                    value[k] = hash(ATT_TYPE(i,j), -1, &k);
+                    double dtmp = hash(ATT_TYPE(i,j), -1, &k);
+                    value[k] = (text)dtmp;
                 }
-                err = ncmpi_put_att_text(ncid, i, ATT_NAME(i,j), 
-                    ATT_LEN(i,j), value);
+                err = PutAtt(text)(ncid, i, ATT_NAME(i,j), ATT_LEN(i,j), value);
                 IF (err != NC_NOERR)
-                    error("%s", ncmpi_strerror(err));
+                    error("%s", APIFunc(strerror)(err));
                 ELSE_NOK
             }
         }
     }
 
-    nok += check_atts_text(ncid);
-    err = ncmpi_close(ncid);
+    nok += check_atts_text(ncid, numGatts, numVars);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 
@@ -1182,71 +1444,86 @@ dnl
 define(`TEST_NC_PUT_ATT',dnl
 `dnl
 int
-test_ncmpi_put_att_$1(void)
+TestFunc(att)_$1(AttVarArgs)
 {
-    int ncid, nok=0;
-    int i;
-    int j;
-    MPI_Offset k;
-    int err;
-    $1 value[MAX_NELS];
+    int i, j, err, ncid, cdf_format, nok=0;
     int allInExtRange;  /* all values within external range? */
+    IntType k;
+    $1 value[MAX_NELS];
 
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    err = FileCreate(scratch, NC_NOCLOBBER);
     IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
+        error("create: %s", APIFunc(strerror)(err));
         return nok;
     }
+
+    err = APIFunc(inq_format)(ncid, &cdf_format);
+    IF (err != NC_NOERR)
+        error("inq_format: %s", APIFunc(strerror)(err));
+
     def_dims(ncid);
-    def_vars(ncid);
+    DefVars(ncid, numVars);
+
+    /* check if can detect a bad file ID */
+    err = PutAtt($1)(BAD_ID, 0, NULL, 0, 0, NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutAtt($1)(ncid, BAD_VARID, NULL, 0, 0, NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
 
     for (i = -1; i < numVars; i++) {
         for (j = 0; j < NATTS(i); j++) {
             if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                 assert(ATT_LEN(i,j) <= MAX_NELS);
-                err = ncmpi_put_att_$1(BAD_ID, i, ATT_NAME(i,j), ATT_TYPE(i,j), 
-                    ATT_LEN(i,j), value);
-                IF (err != NC_EBADID)
-                    error("expecting bad ncid, but err = %d", err);
-                ELSE_NOK
-                err = ncmpi_put_att_$1(ncid, BAD_VARID, ATT_NAME(i,j), 
-                    ATT_TYPE(i,j), ATT_LEN(i,j), value);
+
+                err = PutAtt($1)(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                 IF (err != NC_ENOTVAR)
-                    error("expecting bad var id, but err = %d", err);
+                    EXPECT_ERR(NC_ENOTVAR, err)
                 ELSE_NOK
-                err = ncmpi_put_att_$1(ncid, i, ATT_NAME(i,j), BAD_TYPE, 
-                    ATT_LEN(i,j), value);
+
+                /* check if can detect a bad name */
+                err = PutAtt($1)(ncid, i, NULL, 0, 0, NULL);
+                IF (err != NC_EBADNAME)
+                    EXPECT_ERR(NC_EBADNAME, err)
+                ELSE_NOK
+
+                err = PutAtt($1)(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                 IF (err != NC_EBADTYPE)
-                    error("expecting bad type, but err = %d", err);
+                    EXPECT_ERR(NC_EBADTYPE, err)
                 ELSE_NOK
+
                 for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
-                    value[k] = hash_$1(ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1));
+                    value[k] = hash_$1(cdf_format,ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1));
                     IfCheckTextChar($1, ATT_TYPE(i,j))
-                        allInExtRange &= inRange3(value[k], ATT_TYPE(i,j), NCT_ITYPE($1));
+                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_ITYPE($1));
                 }
-                err = ncmpi_put_att_$1(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j),
-                    ATT_LEN(i,j), value);
+                err = PutAtt($1)(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                 if (allInExtRange) {
                     IF (err != NC_NOERR)
-                        error("%s", ncmpi_strerror(err));
+                        error("%s", APIFunc(strerror)(err));
                     ELSE_NOK
                 } else {
                     IF (err != NC_ERANGE)
-                        error("expecting range error, but err = %d", err);
+                        EXPECT_ERR(NC_ERANGE, err)
                     ELSE_NOK
                 }
             }
         }
     }
 
-    nok += check_atts_$1(ncid);
-    err = ncmpi_close(ncid);
+    nok += check_atts_$1(ncid, numGatts, numVars);
+    err = APIFunc(close)(ncid);
     IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
+        error("close: %s", APIFunc(strerror)(err));
 
-    err = ncmpi_delete(scratch, info);
+    err = FileDelete(scratch, info);
     IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
+        error("delete file %s failed", scratch);
     return nok;
 }
 ')dnl
diff --git a/test/nc_test/test_read.c b/test/nc_test/test_read.c
deleted file mode 100644
index 18c9169..0000000
--- a/test/nc_test/test_read.c
+++ /dev/null
@@ -1,1792 +0,0 @@
-/*
- *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
- *  See COPYRIGHT notice in top-level directory.
- *
- *  $Id: test_read.c 2297 2016-01-06 22:22:33Z wkliao $
- */
-
-#include <sys/types.h> /* open() */
-#include <sys/stat.h> /* open() */
-#include <fcntl.h> /* open() */
-#include <unistd.h> /* unlink(), write() */
-#include "tests.h"
-
-/* 
- * Test ncmpi_strerror.
- *    Try on a bad error status.
- *    Test for each defined error status.
- */
-int
-test_ncmpi_strerror(void)
-{
-    int i;
-    const char *message, *expected_msg;
-    int nok=0;
-
-    static const struct {
-	int status;
-	const char *msg;
-    } ncerrs[] = {
-        {NC_NOERR, "No error"},
-        {NC_EBADID, "NetCDF: Not a valid ID"},
-        {NC_ENFILE, "NetCDF: Too many files open"},
-        {NC_EEXIST, "NetCDF: File exists && NC_NOCLOBBER"},
-        {NC_EINVAL, "NetCDF: Invalid argument"},
-        {NC_EPERM, "NetCDF: Write to read only"},
-        {NC_ENOTINDEFINE, "NetCDF: Operation not allowed in data mode"},
-        {NC_EINDEFINE, "NetCDF: Operation not allowed in define mode"},
-        {NC_EINVALCOORDS, "NetCDF: Index exceeds dimension bound"},
-        {NC_EMAXDIMS, "NetCDF: NC_MAX_DIMS exceeded"},
-        {NC_ENAMEINUSE, "NetCDF: String match to name in use"},
-        {NC_ENOTATT, "NetCDF: Attribute not found"},
-        {NC_EMAXATTS, "NetCDF: NC_MAX_ATTRS exceeded"},
-        {NC_EBADTYPE, "NetCDF: Not a valid data type or _FillValue type mismatch"},
-        {NC_EBADDIM, "NetCDF: Invalid dimension ID or name"},
-        {NC_EUNLIMPOS, "NetCDF: NC_UNLIMITED in the wrong index"},
-        {NC_EMAXVARS, "NetCDF: NC_MAX_VARS exceeded"},
-        {NC_ENOTVAR, "NetCDF: Variable not found"},
-        {NC_EGLOBAL, "NetCDF: Action prohibited on NC_GLOBAL varid"},
-        {NC_ENOTNC, "NetCDF: Unknown file format"},
-        {NC_ESTS, "NetCDF: In Fortran, string too short"},
-        {NC_EMAXNAME, "NetCDF: NC_MAX_NAME exceeded"},
-        {NC_EUNLIMIT, "NetCDF: NC_UNLIMITED size already in use"},
-        {NC_ENORECVARS, "NetCDF: nc_rec op when there are no record vars"},
-        {NC_ECHAR, "NetCDF: Attempt to convert between text & numbers"},
-        {NC_EEDGE, "NetCDF: Start+count exceeds dimension bound"},
-        {NC_ESTRIDE, "NetCDF: Illegal stride"},
-        {NC_EBADNAME, "NetCDF: Name contains illegal characters"},
-        {NC_ERANGE, "NetCDF: Numeric conversion not representable"},
-        {NC_ENOMEM, "NetCDF: Memory allocation (malloc) failure"},
-        {NC_EVARSIZE, "NetCDF: One or more variable sizes violate format constraints"},
-        {NC_EDIMSIZE, "NetCDF: Invalid dimension size"}
-    };
-
-    /* Try on a bad error status */
-    message = ncmpi_strerror(-666);/* should fail */
-    expected_msg = "Unknown Error";
-    IF (strncmp(message, expected_msg, strlen(expected_msg)) != 0)
-	error("ncmpi_strerror on bad error status returned: %s", message);
-    ELSE_NOK
-
-    /* Try on each legitimate error status */
-    for (i=0; i<LEN_OF(ncerrs); i++) {
-	const char *message = ncmpi_strerror(ncerrs[i].status);
-	IF (strcmp(message, ncerrs[i].msg) != 0)
-	    error("ncmpi_strerror(%d) should return `%s', not `%s'",
-		  ncerrs[i].status, ncerrs[i].msg, message);
-        ELSE_NOK
-    }
-    return nok;
-}
-
-
-/* 
- * Test ncmpi_open.
- * If in read-only section of tests,
- *    Try to open a non-existent netCDF file, check error return.
- *    Open a file that is not a netCDF file, check error return.
- *    Open a netCDF file with a bad mode argument, check error return.
- *    Open a netCDF file with NC_NOWRITE, info mode, try to write, check error.
- *    Try to open a netcdf twice, check whether returned netcdf ids different.
- * If in writable section of tests,
- *    Open a netCDF file with NC_WRITE mode, write something, close it.
- * On exit, any open netCDF files are closed.
- */
-#define NOT_NC_FILE "dummy_not_nc_file"
-int
-test_ncmpi_open(void)
-{
-    int err, fd;
-    int ncid;
-    int ncid2;
-    int nok=0;
-    ssize_t w_len;
-    
-    /* Try to open a nonexistent file */
-    err = ncmpi_open(comm, "tooth-fairy.nc", NC_NOWRITE, info, &ncid);/* should fail */
-
-    /* on some systems, opening an nonexisting file will actually create the
-     * file. In this case, we print the error messages on screen and move on
-     * to the next test, instead of aborting the entire test.
-     */
-    if (err == NC_NOERR)
- 	fprintf(stderr, "opening a nonexistent file expects to fail, but got NC_NOERR\n");
-    else if (err != NC_ENOENT)
-	fprintf(stderr, "opening a nonexistent file expects NC_ENOENT, but got %s\n",nc_err_code_name(err));
-    else {
-        /* printf("Expected error message complaining: \"File tooth-fairy.nc does not exist\"\n"); */
-        nok++;
-    }
-
-    /* create a not-nc file */
-    fd = open(NOT_NC_FILE, O_CREAT|O_WRONLY, 0600);
-    w_len = write(fd, "0123456789abcdefghijklmnopqrstuvwxyz", 36);
-    assert(w_len >= 0);
-    close(fd);
-
-    /* Open a file that is not a netCDF file. */
-    err = ncmpi_open(comm, NOT_NC_FILE, NC_NOWRITE, info, &ncid);/* should fail */
-    IF (err != NC_ENOTNC)
-	error("ncmpi_open of non-netCDF file: expecting NC_ENOTNC but got %s", nc_err_code_name(err));
-    ELSE_NOK
-
-    /* delete the not-nc file */
-    unlink(NOT_NC_FILE);
-
-    /* Open a netCDF file in read-only mode, check that write fails */
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    err = ncmpi_redef(ncid);	/* should fail */
-    IF (err != NC_EPERM)
-	error("ncmpi_redef of read-only file should fail");
-    /* Opened OK, see if can open again and get a different netCDF ID */
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid2);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    else {
-	ncmpi_close(ncid2);
-        nok++;
-    }
-    IF (ncid2 == ncid)
-	error("netCDF IDs for first and second ncmpi_open calls should differ");
-
-    if (! read_only) {		/* tests using netCDF scratch file */
-	err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid2);
-	IF (err != NC_NOERR) 
-	    error("ncmpi_create: %s", ncmpi_strerror(err));
-	else 
-	    ncmpi_close(ncid2);
-	err = ncmpi_open(comm, scratch, NC_WRITE, info, &ncid2);
-	IF (err != NC_NOERR) 
-	    error("ncmpi_open: %s", ncmpi_strerror(err));
-	else {
-	    ncmpi_close(ncid2);
-            nok++;
-        }
-	err = ncmpi_delete(scratch, info);
-	IF (err != NC_NOERR) 
-	    error("remove of %s failed", scratch);
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-/* 
- * Test ncmpi_close.
- *    Try to close a netCDF file twice, check whether second close fails.
- *    Try on bad handle, check error return.
- *    Try in define mode and data mode.
- */
-int
-test_ncmpi_close(void)
-{
-    int ncid, nok=0;
-    int err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-
-    /* Close a netCDF file twice, second time should fail */
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close failed: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    err = ncmpi_close(ncid);
-    IF (err != NC_EBADID)
-	error("ncmpi_close of closed file should have failed");
-    ELSE_NOK
-    
-    /* Try with a bad netCDF ID */
-    err = ncmpi_close(BAD_ID);/* should fail */
-    IF (err != NC_EBADID)
-	error("ncmpi_close with bad netCDF ID returned wrong error (%d)", err);
-    ELSE_NOK
-
-    /* Close in data mode */
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close in data mode failed: %s", ncmpi_strerror(err));
-    ELSE_NOK
-
-    if (! read_only) {		/* tests using netCDF scratch file */
-        err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-        IF (err != NC_NOERR) 
-            error("ncmpi_create: %s", ncmpi_strerror(err));
-	err = ncmpi_close(ncid);
-	IF (err != NC_NOERR)
-	    error("ncmpi_close in define mode: %s", ncmpi_strerror(err));
-        ELSE_NOK
-        err = ncmpi_delete(scratch, info);
-        IF (err != NC_NOERR)
-            error("remove of %s failed", scratch);
-    }
-    return nok;
-}
-
-
-/* 
- * Test ncmpi_inq.
- *    Try on bad handle, check error return.
- *    Try in data mode, check returned values.
- *    Try asking for subsets of info.
- * If in writable section of tests,
- *    Try in define mode, after adding an unlimited dimension, variable.
- * On exit, any open netCDF files are closed.
- */
-int
-test_ncmpi_inq(void)
-{
-    int ncid;
-    int ndims;			/* number of dimensions */
-    int nvars;			/* number of variables */
-    int ngatts;			/* number of global attributes */
-    int recdim;			/* id of unlimited dimension */
-    int err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    int nok=0;
-
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    
-    /* Try on bad handle */
-    err = ncmpi_inq(BAD_ID, 0, 0, 0, 0);
-    IF (err != NC_EBADID)
-	error("bad ncid: status = %d", err);
-    ELSE_NOK
-    
-    err = ncmpi_inq(ncid, &ndims, &nvars, &ngatts, &recdim);
-    IF (err != NC_NOERR)
-	error("ncmpi_inq: %s", ncmpi_strerror(err));
-    else IF (ndims != NDIMS)
-	error("ncmpi_inq: wrong number of dimensions returned, %d", ndims);
-    else IF (nvars != numVars)
-	error("ncmpi_inq: wrong number of variables returned, %d", nvars);
-    else IF (ngatts != numGatts)
-	error("ncmpi_inq: wrong number of global atts returned, %d", ngatts);
-    else IF (recdim != RECDIM)
-	error("ncmpi_inq: wrong record dimension ID returned, %d", recdim);
-    ELSE_NOK
-    
-    /* Inguire for no info (useless, but should still work) */
-    err = ncmpi_inq(ncid, 0, 0, 0, 0);
-    IF (err != NC_NOERR)
-	error("ncmpi_inq for no info failed: %s", ncmpi_strerror(err));
-    ELSE_NOK
-
-    /* Inguire for subsets of info */
-    ngatts = numGatts - 1;	/* wipe out previous correct value */
-    err = ncmpi_inq(ncid, 0, 0, &ngatts, 0);
-    IF (err != NC_NOERR)
-	error("ncmpi_inq for one item failed: %s", ncmpi_strerror(err));
-    else IF (ngatts != numGatts)
-	error("ncmpi_inq subset: wrong number of global atts returned, %d", ngatts);
-    ELSE_NOK
-    ndims = NDIMS - 1;
-    nvars = numVars - 1;
-    err = ncmpi_inq(ncid, &ndims, &nvars, 0, 0);
-    IF (err != NC_NOERR)
-	error("ncmpi_inq for two items failed: %s", ncmpi_strerror(err));
-    else IF (ndims != NDIMS)
-	error("ncmpi_inq subset: wrong number of dimensions returned, %d", ndims);
-    else IF (nvars != numVars)
-	error("ncmpi_inq subset: wrong number of variables returned, %d", nvars);
-    ELSE_NOK
-
-    if (! read_only) {		/* tests using netCDF scratch file */
-	int ncid2;		/* for scratch netCDF dataset */
-
-        err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid2);
-        IF (err != NC_NOERR) {
-            error("ncmpi_create: %s", ncmpi_strerror(err));
-	} else {		/* add dim, var, gatt, check inq */
-	    int ndims0;
-	    int nvars0;
-	    int ngatts0;
-	    int recdim0;
-	    err = ncmpi_enddef(ncid2); /* enter data mode */
-	    err = ncmpi_inq(ncid2, &ndims0, &nvars0, &ngatts0, &recdim0);
-	    IF (err != NC_NOERR)
-		error("ncmpi_inq: %s", ncmpi_strerror(err));
-            ELSE_NOK
-	    err = ncmpi_redef(ncid2); /* enter define mode */
-	    /* Check that inquire still works in define mode */
-	    err = ncmpi_inq(ncid2, &ndims, &nvars, &ngatts, &recdim);
-	    IF (err != NC_NOERR)
-		error("ncmpi_inq in define mode: %s", ncmpi_strerror(err));
-	    else IF (ndims != ndims0)
-		error("ncmpi_inq in define mode: ndims wrong, %d", ndims);
-	    else IF (nvars != nvars0)
-		error("ncmpi_inq in define mode: nvars wrong, %d", nvars);
-	    else IF (ngatts != ngatts0)
-		error("ncmpi_inq in define mode: ngatts wrong, %d", ngatts);
-	    else IF (recdim != recdim0)
-		error("ncmpi_inq in define mode: recdim wrong, %d", recdim);
-            ELSE_NOK
-
-	    {
-		int did, vid;
-		/* Add dim, var, global att */
-		err = ncmpi_def_dim(ncid2, "inqd", 1L, &did);
-		IF (err != NC_NOERR)
-		    error("ncmpi_def_dim: %s", ncmpi_strerror(err));
-		err = ncmpi_def_var(ncid2, "inqv", NC_FLOAT, 0, 0, &vid);
-		IF (err != NC_NOERR)
-		    error("ncmpi_def_var: %s", ncmpi_strerror(err));
-	    }
-	    err = ncmpi_put_att_text(ncid2, NC_GLOBAL, "inqa", 1+strlen("stuff"),
-				   "stuff");
-	    IF (err != NC_NOERR)
-		error("ncmpi_put_att_text: %s", ncmpi_strerror(err));
-
-	    /* Make sure ncmpi_inq sees the additions while in define mode */
-	    err = ncmpi_inq(ncid2, &ndims, &nvars, &ngatts, &recdim);
-	    IF (err != NC_NOERR)
-		error("ncmpi_inq in define mode: %s", ncmpi_strerror(err));
-	    else IF (ndims != ndims0 + 1)
-		error("ncmpi_inq in define mode: ndims wrong, %d", ndims);
-	    else IF (nvars != nvars0 + 1)
-		error("ncmpi_inq in define mode: nvars wrong, %d", nvars);
-	    else IF (ngatts != ngatts0 + 1)
-		error("ncmpi_inq in define mode: ngatts wrong, %d", ngatts);
-            ELSE_NOK
-	    err = ncmpi_enddef(ncid2);
-	    IF (err != NC_NOERR)
-		error("ncmpi_enddef: %s", ncmpi_strerror(err));
-
-	    /* Make sure ncmpi_inq stills sees additions in data mode */
-	    err = ncmpi_inq(ncid2, &ndims, &nvars, &ngatts, &recdim);
-	    IF (err != NC_NOERR)
-		error("ncmpi_inq failed in data mode: %s", ncmpi_strerror(err));
-	    else IF (ndims != ndims0 + 1)
-		error("ncmpi_inq in define mode: ndims wrong, %d", ndims);
-	    else IF (nvars != nvars0 + 1)
-		error("ncmpi_inq in define mode: nvars wrong, %d", nvars);
-	    else IF (ngatts != ngatts0 + 1)
-		error("ncmpi_inq in define mode: ngatts wrong, %d", ngatts);
-            ELSE_NOK
-	    ncmpi_close(ncid2);
-	    err = ncmpi_delete(scratch, info);
-	    IF (err != NC_NOERR)
-		error("remove of %s failed", scratch);
-	}
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_natts(void)
-{
-    int ncid;
-    int ngatts;			/* number of global attributes */
-    int err, nok=0;
-
-    err = ncmpi_inq_natts(BAD_ID, &ngatts);
-    IF (err != NC_EBADID)
-	error("bad ncid: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_inq_natts(ncid, &ngatts);
-    IF (err != NC_NOERR)
-	error("ncmpi_inq_natts: %s", ncmpi_strerror(err));
-    else IF (ngatts != numGatts)
-	error("ncmpi_inq_natts: wrong number of global atts returned, %d", ngatts);
-    ELSE_NOK
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_ndims(void)
-{
-    int ncid;
-    int ndims;
-    int err;
-    int nok=0;
-
-    err = ncmpi_inq_ndims(BAD_ID, &ndims);
-    IF (err != NC_EBADID)
-	error("bad ncid: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_inq_ndims(ncid, &ndims);
-    IF (err != NC_NOERR)
-	error("ncmpi_inq_ndims: %s", ncmpi_strerror(err));
-    else IF (ndims != NDIMS)
-	error("ncmpi_inq_ndims: wrong number returned, %d", ndims);
-    ELSE_NOK
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_nvars(void)
-{
-    int ncid;
-    int nvars;
-    int err;
-    int nok=0;
-
-    err = ncmpi_inq_nvars(BAD_ID, &nvars);
-    IF (err != NC_EBADID)
-	error("bad ncid: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_inq_nvars(ncid, &nvars);
-    IF (err != NC_NOERR)
-	error("ncmpi_inq_nvars: %s", ncmpi_strerror(err));
-    else IF (nvars != numVars)
-	error("ncmpi_inq_nvars: wrong number returned, %d", nvars);
-    ELSE_NOK
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_unlimdim(void)
-{
-    int ncid;
-    int unlimdim;
-    int err;
-    int nok=0;
-
-    err = ncmpi_inq_unlimdim(BAD_ID, &unlimdim);
-    IF (err != NC_EBADID)
-	error("bad ncid: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_inq_unlimdim(ncid, &unlimdim);
-    IF (err != NC_NOERR)
-	error("ncmpi_inq_unlimdim: %s", ncmpi_strerror(err));
-    else IF (unlimdim != RECDIM)
-	error("ncmpi_inq_unlimdim: wrong number returned, %d", unlimdim);
-    ELSE_NOK
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_dimid(void)
-{
-    int ncid;
-    int dimid;
-    int i;
-    int err;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_inq_dimid(ncid, "noSuch", &dimid);
-    IF (err != NC_EBADDIM)
-	error("bad dim name: status = %d", err);
-    ELSE_NOK
-    for (i = 0; i < NDIMS; i++) {
-	err = ncmpi_inq_dimid(BAD_ID, dim_name[i], &dimid);
-	IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_dimid(ncid, dim_name[i], &dimid);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_dimid: %s", ncmpi_strerror(err));
-	else IF (dimid != i)
-	    error("expected %d, got %d", i, dimid);
-        ELSE_NOK
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_dim(void)
-{
-    int ncid;
-    int i;
-    int err;
-    char name[NC_MAX_NAME];
-    MPI_Offset length;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    for (i = 0; i < NDIMS; i++) {
-	err = ncmpi_inq_dim(BAD_ID, i, name, &length);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_dim(ncid, BAD_DIMID, name, &length);
-        IF (err != NC_EBADDIM)
-	    error("bad dimid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_dim(ncid, i, 0, 0);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
-        ELSE_NOK
-	err = ncmpi_inq_dim(ncid, i, name, &length);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
-	else IF (strcmp(dim_name[i],name)) 
-	    error("name expected: %s, got: %s",dim_name[i],name);
-	else IF (dim_len[i] != length)
-	    error("size expected: %d, got: %d",dim_len[i],length);
-        ELSE_NOK
-	err = ncmpi_inq_dim(ncid, i, name, 0);
-        IF (err != NC_NOERR)
-	    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
-	else IF (strcmp(dim_name[i],name)) 
-	    error("name expected: %s, got: %s",dim_name[i],name);
-        ELSE_NOK
-	err = ncmpi_inq_dim(ncid, i, 0, &length);
-        IF (err != NC_NOERR)
-	    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
-	else IF (dim_len[i] != length)
-	    error("size expected: %d, got: %d",dim_len[i],length);
-        ELSE_NOK
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_dimlen(void)
-{
-    int ncid;
-    int i;
-    int err;
-    MPI_Offset  length;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    for (i = 0; i < NDIMS; i++) {
-	err = ncmpi_inq_dimlen(BAD_ID, i, &length);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_dimlen(ncid, BAD_DIMID, &length);
-        IF (err != NC_EBADDIM)
-	    error("bad dimid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_dimlen(ncid, i, &length);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_dimlen: %s", ncmpi_strerror(err));
-	else IF (dim_len[i] != length)
-	    error("size expected: %d, got: %d",dim_len[i],length);
-        ELSE_NOK
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_dimname(void)
-{
-    int ncid;
-    int i;
-    int err;
-    char name[NC_MAX_NAME];
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    for (i = 0; i < NDIMS; i++) {
-	err = ncmpi_inq_dimname(BAD_ID, i, name);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_dimname(ncid, BAD_DIMID, name);
-        IF (err != NC_EBADDIM)
-	    error("bad dimid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_dimname(ncid, i, name);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_dimname: %s", ncmpi_strerror(err));
-	else IF (strcmp(dim_name[i],name)) 
-	    error("name expected: %s, got: %s",dim_name[i],name);
-        ELSE_NOK
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_varid(void)
-{
-    int ncid;
-    int varid;
-    int i;
-    int err;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-
-    err = ncmpi_inq_varid(ncid, "noSuch", &varid);
-    IF (err != NC_ENOTVAR)
-	error("bad ncid: status = %d", err);
-    ELSE_NOK
-
-    for (i = 0; i < numVars; i++) {
-	err = ncmpi_inq_varid(BAD_ID, var_name[i], &varid);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_varid(ncid, var_name[i], &varid);
-        IF (err != NC_NOERR)
-	    error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
-	else IF (varid != i)
-	    error("expected %d, got %d", i, varid);
-        ELSE_NOK
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_var(void)
-{
-    int ncid;
-    int i;
-    int err;
-    char name[NC_MAX_NAME];
-    nc_type datatype;
-    int ndims;
-    int dimids[MAX_RANK];
-    int natts;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    for (i = 0; i < numVars; i++) {
-	err = ncmpi_inq_var(BAD_ID, i, name, &datatype, &ndims, dimids, &natts);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_var(ncid,BAD_VARID,name,&datatype,&ndims,dimids,&natts);
-        IF (err != NC_ENOTVAR)
-	    error("bad var id: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_var(ncid, i, 0, 0, 0, 0, 0);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
-        ELSE_NOK
-	err = ncmpi_inq_var(ncid, i, name, &datatype, &ndims, dimids, &natts);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
-	else IF (strcmp(var_name[i],name)) 
-	    error("name expected: %s, got: %s",var_name[i],name);
-	else IF (var_type[i] != datatype)
-	    error("type expected: %d, got: %d",var_type[i],datatype);
-	else IF (var_rank[i] != ndims)
-	    error("ndims expected: %d, got: %d",var_rank[i],ndims);
-	else IF (!int_vec_eq(var_dimid[i],dimids,ndims))
-	    error("unexpected dimid");
-	else IF (var_natts[i] != natts)
-	    error("natts expected: %d, got: %d",var_natts[i],natts);
-        ELSE_NOK
-	err = ncmpi_inq_var(ncid, i, name, 0, 0, 0, 0);
-        IF (err != NC_NOERR)
-	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
-	else IF (strcmp(var_name[i],name)) 
-	    error("name expected: %s, got: %s",var_name[i],name);
-        ELSE_NOK
-	err = ncmpi_inq_var(ncid, i, 0, &datatype, 0, 0, 0);
-        IF (err != NC_NOERR)
-	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
-        else IF (var_type[i] != datatype)
-            error("type expected: %d, got: %d",var_type[i],datatype);
-        ELSE_NOK
-	err = ncmpi_inq_var(ncid, i, 0, 0, &ndims, 0, 0);
-        IF (err != NC_NOERR)
-	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
-        else IF (var_rank[i] != ndims)
-            error("ndims expected: %d, got: %d",var_rank[i],ndims);
-        ELSE_NOK
-	err = ncmpi_inq_var(ncid, i, 0, 0, 0, dimids, 0);
-        IF (err != NC_NOERR)
-	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
-        else IF (!int_vec_eq(var_dimid[i],dimids,ndims))
-            error("unexpected dimid");
-        ELSE_NOK
-	err = ncmpi_inq_var(ncid, i, 0, 0, 0, 0, &natts);
-        IF (err != NC_NOERR)
-	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
-        else IF (var_natts[i] != natts)
-            error("natts expected: %d, got: %d",var_natts[i],natts);
-        ELSE_NOK
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_vardimid(void)
-{
-    int ncid;
-    int i;
-    int err;
-    int dimids[MAX_RANK];
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    for (i = 0; i < numVars; i++) {
-	err = ncmpi_inq_vardimid(BAD_ID, i, dimids);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_vardimid(ncid, BAD_VARID, dimids);
-        IF (err != NC_ENOTVAR)
-	    error("bad var id: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_vardimid(ncid, i, dimids);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_vardimid: %s", ncmpi_strerror(err));
-	else IF (!int_vec_eq(var_dimid[i], dimids, var_rank[i]))
-	    error("unexpected dimid");
-        ELSE_NOK
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_varname(void)
-{
-    int ncid;
-    int i;
-    int err;
-    char name[NC_MAX_NAME];
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    for (i = 0; i < numVars; i++) {
-	err = ncmpi_inq_varname(BAD_ID, i, name);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        nok++;
-	err = ncmpi_inq_varname(ncid, BAD_VARID, name);
-        IF (err != NC_ENOTVAR)
-	    error("bad var id: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_varname(ncid, i, name);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_varname: %s", ncmpi_strerror(err));
-	else IF (strcmp(var_name[i],name)) 
-	    error("name expected: %s, got: %s",var_name[i],name);
-        ELSE_NOK
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_varnatts(void)
-{
-    int ncid;
-    int i;
-    int err;
-    int natts;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    for (i = -1; i < numVars; i++) {
-	err = ncmpi_inq_varnatts(BAD_ID, i, &natts);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_varnatts(ncid, BAD_VARID, &natts);
-        IF (err != NC_ENOTVAR)
-	    error("bad var id: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_varnatts(ncid, VARID(i), &natts);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_varnatts: %s", ncmpi_strerror(err));
-        else IF (NATTS(i) != natts)
-            error("natts expected: %d, got: %d",NATTS(i),natts);
-        ELSE_NOK
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_varndims(void)
-{
-    int ncid;
-    int i;
-    int err;
-    int ndims;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    for (i = 0; i < numVars; i++) {
-	err = ncmpi_inq_varndims(BAD_ID, i, &ndims);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_varndims(ncid, BAD_VARID, &ndims);
-        IF (err != NC_ENOTVAR)
-	    error("bad var id: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_varndims(ncid, i, &ndims);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_varndims: %s", ncmpi_strerror(err));
-        else IF (var_rank[i] != ndims)
-            error("ndims expected: %d, got: %d",var_rank[i],ndims);
-        ELSE_NOK
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_vartype(void)
-{
-    int ncid;
-    int i;
-    int err;
-    nc_type datatype;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    for (i = 0; i < numVars; i++) {
-	err = ncmpi_inq_vartype(BAD_ID, i, &datatype);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_vartype(ncid, BAD_VARID, &datatype);
-        IF (err != NC_ENOTVAR)
-	    error("bad var id: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_vartype(ncid, i, &datatype);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_vartype: %s", ncmpi_strerror(err));
-        else IF (var_type[i] != datatype)
-            error("type expected: %d, got: %d", var_type[i], datatype);
-        ELSE_NOK
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-/*
- * Test ncmpi_put_var1
- */
-int
-test_ncmpi_get_var1(void)
-{
-    int ncid;
-    int i;
-    int j;
-    int err;
-    double expect;
-    int nok = 0;		/* count of valid comparisons */
-    double buf[1];		/* (void *) buffer */
-    double value;
-    MPI_Offset index[MAX_RANK];
-    MPI_Datatype datatype;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_begin_indep_data(ncid);
-    for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
-	for (j = 0; j < var_rank[i]; j++)
-	    index[j] = 0;
-        err = ncmpi_get_var1(BAD_ID, i, index, buf, 1, datatype);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_get_var1(ncid, BAD_VARID, index, buf, 1, datatype);
-        IF (err != NC_ENOTVAR)
-	    error("bad var id: status = %d", err);
-        ELSE_NOK
-	for (j = 0; j < var_rank[i]; j++) {
-	    index[j] = var_shape[i][j];
-	    err = ncmpi_get_var1(ncid, i, index, buf, 1, datatype);
-            IF (err != NC_EINVALCOORDS)
-                error("bad index: status = %d", err);
-            ELSE_NOK
-	    index[j] = 0;
-	}
-        for (j = 0; j < var_nels[i]; j++) {
-	    err = toMixedBase(j, var_rank[i], var_shape[i], index);
-	    IF (err != NC_NOERR)
-		error("error in toMixedBase 2");
-	    expect = hash( var_type[i], var_rank[i], index );
-            if (var_rank[i] == 0 && i%2 )
-		err = ncmpi_get_var1(ncid, i, NULL, buf, 1, datatype);
-	    else
-		err = ncmpi_get_var1(ncid, i, index, buf, 1, datatype);
-	    IF (err != NC_NOERR)
-		error("%s", ncmpi_strerror(err));
-            ELSE_NOK
-	    err = nc2dbl( var_type[i], buf, &value );
-	    IF (err != NC_NOERR)
-		error("error in nc2dbl");
-	    if (inRange(expect,var_type[i])) {
-		IF (!equal2(value,expect,var_type[i]))
-		    error("expected: %G, got: %G", expect, value);
-                ELSE_NOK
-	    }
-        }
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-/*
- * Test ncmpi_get_vara
- * Choose a random point dividing each dim into 2 parts
- * Get 2^rank (nslabs) slabs so defined
- * Each get overwrites buffer, so check after each get.
- */
-int
-test_ncmpi_get_vara(void)
-{
-    int ncid, d, i, j, k, err, nels, nslabs;
-    int nok = 0;      /* count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Datatype datatype;
-    double buf[MAX_NELS];	/* (void *) buffer */
-    double expect;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_begin_indep_data(ncid);
-    for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
-        assert(var_rank[i] <= MAX_RANK);
-        assert(var_nels[i] <= MAX_NELS);
-        for (j = 0; j < var_rank[i]; j++) {
-            start[j] = 0;
-            edge[j] = 1;
-        }
-        err = ncmpi_get_vara(BAD_ID, i, start, edge, buf, 1, datatype);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_get_vara(ncid, BAD_VARID, start, edge, buf, 1, datatype);
-        IF (err != NC_ENOTVAR)
-	    error("bad var id: status = %d", err);
-        ELSE_NOK
-	for (j = 0; j < var_rank[i]; j++) {
-	    start[j] = var_shape[i][j];
-	    err = ncmpi_get_vara(ncid, i, start, edge, buf, 1, datatype);
-            IF (err != NC_EINVALCOORDS)
-                error("bad index: status = %d", err);
-            ELSE_NOK
-	    start[j] = 0;
-	    edge[j] = var_shape[i][j] + 1;
-	    err = ncmpi_get_vara(ncid, i, start, edge, buf, 1, datatype);
-            IF (err != NC_EEDGE)
-		error("bad edge: status = %d", err);
-            ELSE_NOK
-	    edge[j] = 1;
-	}
-            /* Choose a random point dividing each dim into 2 parts */
-            /* get 2^rank (nslabs) slabs so defined */
-        nslabs = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            mid[j] = roll( var_shape[i][j] );
-            nslabs *= 2;
-        }
-            /* bits of k determine whether to get lower or upper part of dim */
-        for (k = 0; k < nslabs; k++) {
-            nels = 1;
-            for (j = 0; j < var_rank[i]; j++) {
-                if ((k >> j) & 1) {
-                    start[j] = 0;
-                    edge[j] = mid[j];
-                }else{
-                    start[j] = mid[j];
-                    edge[j] = var_shape[i][j] - mid[j];
-                }
-                nels *= edge[j];
-            }
-            if (var_rank[i] == 0 && i%2 )
-		err = ncmpi_get_vara(ncid, i, NULL, NULL, buf, nels, datatype);
-	    else
-		err = ncmpi_get_vara(ncid, i, start, edge, buf, nels, datatype);
-	    IF (err != NC_NOERR) {
-		error("%s", ncmpi_strerror(err));
-	    } else {
-	        nok++;
-		for (j = 0; j < nels; j++) {
-                    double got;
-                    char *p = (char *) buf;
-                    p += j * nctypelen(var_type[i]);
-		    err = nc2dbl( var_type[i], p, & got );
-		    IF (err != NC_NOERR)
-			error("error in nc2dbl");
-		    err = toMixedBase(j, var_rank[i], edge, index);
-		    IF (err != NC_NOERR)
-			error("error in toMixedBase 1");
-		    for (d = 0; d < var_rank[i]; d++)
-			index[d] += start[d];
-		    expect = hash(var_type[i], var_rank[i], index);
-		    if (inRange(expect,var_type[i])) {
-			IF (!equal2(got,expect,var_type[i])) {
-			    error("value read not that expected");
-			    if (verbose) {
-				error("\n");
-				error("varid: %d, ", i);
-				error("var_name: %s, ", var_name[i]);
-				error("element number: %d ", j);
-				error("expect: %g", expect);
-				error("got: %g", got);
-			    }
-			}
-		    }
-		}
-	    }
-	}
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-/*
- * Test ncmpi_get_vars
- * Choose a random point dividing each dim into 2 parts
- * Get 2^rank (nslabs) slabs so defined
- * Each get overwrites buffer, so check after each get.
- */
-int
-test_ncmpi_get_vars(void)
-{
-    int ncid;
-    int d;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err;
-    int nels;
-    int nslabs;
-    int nstarts;	/* number of different starts */
-    int nok = 0;	/* total count of valid comparisons */
-    int n;		/* count of valid comparisons within var */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    MPI_Datatype datatype;
-    double buf[MAX_NELS];     /* (void *) buffer */
-    char *p;			/* (void *) pointer */
-    double expect;
-    double got;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_begin_indep_data(ncid);
-    for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
-        assert(var_rank[i] <= MAX_RANK);
-        assert(var_nels[i] <= MAX_NELS);
-        for (j = 0; j < var_rank[i]; j++) {
-            start[j] = 0;
-            edge[j] = 1;
-            stride[j] = 1;
-        }
-        err = ncmpi_get_vars(BAD_ID, i, start, edge, stride, buf, 1, datatype);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_get_vars(ncid, BAD_VARID, start, edge, stride, buf, 1, datatype);
-        IF (err != NC_ENOTVAR)
-	    error("bad var id: status = %d", err);
-        ELSE_NOK
-	for (j = 0; j < var_rank[i]; j++) {
-	    start[j] = var_shape[i][j];
-	    err = ncmpi_get_vars(ncid, i, start, edge, stride, buf, 1, datatype);
-            IF (err != NC_EINVALCOORDS)
-                error("bad index: status = %d", err);
-            ELSE_NOK
-	    start[j] = 0;
-	    edge[j] = var_shape[i][j] + 1;
-	    err = ncmpi_get_vars(ncid, i, start, edge, stride, buf, 1, datatype);
-            IF (err != NC_EEDGE)
-		error("bad edge: status = %d", err);
-            ELSE_NOK
-	    edge[j] = 1;
-	    stride[j] = 0;
-	    err = ncmpi_get_vars(ncid, i, start, edge, stride, buf, 1, datatype);
-            IF (err != NC_ESTRIDE)
-		error("bad stride: status = %d", err);
-            ELSE_NOK
-	    stride[j] = 1;
-	}
-        /* Choose a random point dividing each dim into 2 parts */
-        /* get 2^rank (nslabs) slabs so defined */
-        nslabs = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            mid[j] = roll( var_shape[i][j] );
-            nslabs *= 2;
-        }
-        /* bits of k determine whether to get lower or upper part of dim */
-	/* choose random stride from 1 to edge */
-	n = 0;
-        for (k = 0; k < nslabs; k++) {
-            nstarts = 1;
-            for (j = 0; j < var_rank[i]; j++) {
-                if ((k >> j) & 1) {
-                    start[j] = 0;
-                    edge[j] = mid[j];
-                }else{
-                    start[j] = mid[j];
-                    edge[j] = var_shape[i][j] - mid[j];
-                }
-		sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
-                nstarts *= stride[j];
-            }
-	    for (m = 0; m < nstarts; m++) {
-		err = toMixedBase(m, var_rank[i], sstride, index);
-		IF (err != NC_NOERR)
-		    error("error in toMixedBase");
-		nels = 1;
-		for (j = 0; j < var_rank[i]; j++) {
-		    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
-		    nels *= count[j];
-		    index[j] += start[j];
-		}
-		/* Random choice of forward or backward */
-/* TODO
-		if ( roll(2) ) {
-		    for (j = 0; j < var_rank[i]; j++) {
-			index[j] += (count[j] - 1) * stride[j];
-			stride[j] = -stride[j];
-		    }
-		}
- */
-		if (var_rank[i] == 0 && i%2 )
-		    err = ncmpi_get_vars(ncid, i, NULL, NULL, NULL, buf, 1, datatype);
-		else
-		    err = ncmpi_get_vars(ncid, i, index, count, stride, buf, nels, datatype);
-		IF (err != NC_NOERR) {
-		    error("%s", ncmpi_strerror(err));
-		} else {
-		    nok++;
-		    for (j = 0; j < nels; j++) {
-			p = (char *) buf;
-			p += j * nctypelen(var_type[i]);
-			err = nc2dbl( var_type[i], p, & got );
-			IF (err != NC_NOERR)
-			    error("error in nc2dbl");
-			err = toMixedBase(j, var_rank[i], count, index2);
-			IF (err != NC_NOERR)
-			    error("error in toMixedBase 1");
-			for (d = 0; d < var_rank[i]; d++)
-			    index2[d] = index[d] + index2[d] * stride[d];
-			expect = hash(var_type[i], var_rank[i], index2);
-			if (inRange(expect,var_type[i])) {
-			    IF (!equal2(got,expect,var_type[i])) {
-				error("value read not that expected");
-				if (verbose) {
-				    error("\n");
-				    error("varid: %d, ", i);
-				    error("var_name: %s, ", var_name[i]);
-				    error("element number: %d ", j);
-				    error("expect: %g, ", expect);
-				    error("got: %g ", got);
-				}
-			    }
-			}
-			n++;
-		    }
-		}
-	    }
-	}
-	IF (n != var_nels[i]) {
-	    error("count != nels");
-	    if (verbose) {
-		error("\n");
-		error("varid: %d, ", i);
-		error("var_name: %s, ", var_name[i]);
-		error("count: %d, ", n);
-		error("nels: %d ", var_nels[i]);
-	    }
-	}
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-/*
- * Test ncmpi_get_varm
- * Choose a random point dividing each dim into 2 parts
- * Get 2^rank (nslabs) slabs so defined
- * Choose random stride from 1 to edge
- * Buffer should end up being bit image of external variable.
- * So all gets for a variable store in different elements of buffer
- */
-int
-test_ncmpi_get_varm(void)
-{
-    int ncid;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err;
-    int nslabs;
-    int nstarts;	/* number of different starts */
-    int nok = 0;	/* total count of valid comparisons */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    MPI_Offset imap[MAX_RANK];
-    MPI_Offset imap2[MAX_RANK];
-    MPI_Offset nels;
-    MPI_Datatype datatype;
-    double buf[MAX_NELS];	/* (void *) buffer */
-    char *p;			/* (void *) pointer */
-    double expect;
-    double got;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_begin_indep_data(ncid);
-    for (i = 0; i < numVars; i++) {
-        datatype = nc_mpi_type(var_type[i]);
-        assert(var_rank[i] <= MAX_RANK);
-        assert(var_nels[i] <= MAX_NELS);
-        for (j = 0; j < var_rank[i]; j++) {
-            start[j] = 0;
-            edge[j] = 1;
-            stride[j] = 1;
-        }
-        if (var_rank[i] > 0) {
-            j = var_rank[i] - 1;
-            /* imap[j] = nctypelen(var_type[i]); */
-            imap[j] = 1; /* in numbers of elements */
-            for (; j > 0; j--)
-                imap[j-1] = imap[j] * var_shape[i][j];
-        }
-        err = ncmpi_get_varm(BAD_ID, i, start, edge, stride, imap, buf, 1, datatype);
-        IF (err != NC_EBADID)
-	    error("bad ncid: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_get_varm(ncid, BAD_VARID, start, edge, stride, imap, buf, 1, datatype);
-        IF (err != NC_ENOTVAR)
-	    error("bad var id: status = %d", err);
-        ELSE_NOK
-	for (j = 0; j < var_rank[i]; j++) {
-	    start[j] = var_shape[i][j];
-	    err = ncmpi_get_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
-            IF (err != NC_EINVALCOORDS)
-                error("bad index: status = %d", err);
-            ELSE_NOK
-	    start[j] = 0;
-	    edge[j] = var_shape[i][j] + 1;
-	    err = ncmpi_get_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
-            IF (err != NC_EEDGE)
-		error("bad edge: status = %d", err);
-            ELSE_NOK
-	    edge[j] = 1;
-	    stride[j] = 0;
-	    err = ncmpi_get_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
-            IF (err != NC_ESTRIDE)
-		error("bad stride: status = %d", err);
-            ELSE_NOK
-	    stride[j] = 1;
-	}
-            /* Choose a random point dividing each dim into 2 parts */
-            /* get 2^rank (nslabs) slabs so defined */
-        nslabs = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            mid[j] = roll( var_shape[i][j] );
-            nslabs *= 2;
-        }
-            /* bits of k determine whether to get lower or upper part of dim */
-	    /* choose random stride from 1 to edge */
-        for (k = 0; k < nslabs; k++) {
-            nstarts = 1;
-            for (j = 0; j < var_rank[i]; j++) {
-                if ((k >> j) & 1) {
-                    start[j] = 0;
-                    edge[j] = mid[j];
-                }else{
-                    start[j] = mid[j];
-                    edge[j] = var_shape[i][j] - mid[j];
-                }
-		sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
-		imap2[j] = imap[j] * sstride[j];
-                nstarts *= stride[j];
-            }
-	    for (m = 0; m < nstarts; m++) {
-		if (var_rank[i] == 0 && i%2 ) {
-		    err = ncmpi_get_varm(ncid, i, NULL, NULL, NULL, NULL, buf, var_nels[i], datatype);
-		} else {
-		    err = toMixedBase(m, var_rank[i], sstride, index);
-		    IF (err != NC_NOERR)
-			error("error in toMixedBase");
-                    nels = 1;
-		    for (j = 0; j < var_rank[i]; j++) {
-			count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
-			index[j] += start[j];
-                        nels *= count[j];
-		    }
-			    /* Random choice of forward or backward */
-/* TODO
-		    if ( roll(2) ) {
-			for (j = 0; j < var_rank[i]; j++) {
-			    index[j] += (count[j] - 1) * stride[j];
-			    stride[j] = -stride[j];
-			}
-		    }
- */
-		    j = fromMixedBase(var_rank[i], index, var_shape[i]);
-		    p = (char *) buf + j * nctypelen(var_type[i]);
-		    err = ncmpi_get_varm(ncid, i, index, count, stride, imap2, p, nels, datatype);
-		}
-		IF (err != NC_NOERR)
-		    error("%s", ncmpi_strerror(err));
-                ELSE_NOK
-	    }
-	}
-        p = (char *) buf;
-	for (j = 0; j < var_nels[i]; j++) {
-            err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR)
-                error("error in toMixedBase");
-            expect = hash( var_type[i], var_rank[i], index);
-	    err = nc2dbl( var_type[i], p, & got );
-	    IF (err != NC_NOERR)
-		error("error in nc2dbl");
-	    if (inRange(expect,var_type[i])) {
-		IF (!equal2(got,expect,var_type[i])) {
-		    error("value read not that expected");
-		    if (verbose) {
-			error("\n");
-			error("varid: %d, ", i);
-			error("var_name: %s, ", var_name[i]);
-			error("element number: %d ", j);
-			error("expect: %g, ", expect);
-			error("got: %g ", got);
-		    }
-		}
-                ELSE_NOK
-	    }
-            p += nctypelen(var_type[i]);
-	}
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_get_att(void)
-{
-    int ncid;
-    int i;
-    int j;
-    MPI_Offset k;
-    int err;
-    double buf[MAX_NELS];	/* (void *) buffer */
-    char *p;			/* (void *) pointer */
-    double expect;
-    double got;
-    int nok = 0;      /* count of valid comparisons */
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR) 
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-
-    for (i = -1; i < numVars; i++) {
-        for (j = 0; j < NATTS(i); j++) {
-	    err = ncmpi_get_att(BAD_ID, i, ATT_NAME(i,j), buf);
-	    IF (err != NC_EBADID) 
-		error("bad ncid: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_get_att(ncid, BAD_VARID, ATT_NAME(i,j), buf);
-	    IF (err != NC_ENOTVAR) 
-		error("bad var id: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_get_att(ncid, i, "noSuch", buf);
-	    IF (err != NC_ENOTATT) 
-		error("Bad attribute name: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_get_att(ncid, i, ATT_NAME(i,j), buf);
-	    IF (err != NC_NOERR) {
-		error("%s", ncmpi_strerror(err));
-	    } else {
-		nok++;
-		for (k = 0; k < ATT_LEN(i,j); k++) {
-		    expect = hash(ATT_TYPE(i,j), -1, &k );
-		    p = (char *) buf;
-		    p += k * nctypelen(ATT_TYPE(i,j));
-		    err = nc2dbl( ATT_TYPE(i,j), p, &got );
-		    IF (err != NC_NOERR)
-			error("error in nc2dbl");
-		    if (inRange(expect,ATT_TYPE(i,j))) {
-			IF (!equal2(got,expect,ATT_TYPE(i,j))) {
-			    error("value read not that expected");
-			    if (verbose) {
-				error("\n");
-				error("varid: %d, ", i);
-				error("var_name: %s, ",
-					i >= 0 ? var_name[i] : "Global");
-				error("att_name: %s, ", ATT_NAME(i,j));
-				error("element number: %d\n", k);
-				error("expect: %-23.16e\n", expect);
-				error("   got: %-23.16e", got);
-			    }
-			}
-		    }
-                }
-	    }
-	}
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_att(void)
-{
-    int ncid;
-    int i;
-    int j;
-    int err;
-    nc_type t;
-    MPI_Offset n;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR) 
-	error("ncmpi_open: %s", ncmpi_strerror(err));
-
-    for (i = -1; i < numVars; i++) {
-        for (j = 0; j < NATTS(i); j++) {
-	    err = ncmpi_inq_att(BAD_ID, i, ATT_NAME(i,j), &t, &n);
-	    IF (err != NC_EBADID) 
-		error("bad ncid: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_inq_att(ncid, BAD_VARID, ATT_NAME(i,j), &t, &n);
-	    IF (err != NC_ENOTVAR) 
-		error("bad var id: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_inq_att(ncid, i, "noSuch", &t, &n);
-	    IF (err != NC_ENOTATT) 
-		error("Bad attribute name: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_inq_att(ncid, i, ATT_NAME(i,j), &t, &n);
-	    IF (err != NC_NOERR) {
-		error("%s", ncmpi_strerror(err));
-	    } else {
-		IF (t != ATT_TYPE(i,j))
-		    error("type not that expected");
-		else IF (n != ATT_LEN(i,j)) 
-		    error("length not that expected");
-                ELSE_NOK
-	    }
-	}
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_attlen(void)
-{
-    int ncid;
-    int i;
-    int j;
-    int err;
-    MPI_Offset len;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-
-    for (i = -1; i < numVars; i++) {
-	err = ncmpi_inq_attlen(ncid, i, "noSuch", &len);
-	IF (err != NC_ENOTATT)
-	    error("Bad attribute name: status = %d", err);
-        ELSE_NOK
-        for (j = 0; j < NATTS(i); j++) {
-            err = ncmpi_inq_attlen(BAD_ID, i, ATT_NAME(i,j), &len);
-            IF (err != NC_EBADID)
-                error("bad ncid: status = %d", err);
-            ELSE_NOK
-            err = ncmpi_inq_attlen(ncid, BAD_VARID, ATT_NAME(i,j), &len);
-            IF (err != NC_ENOTVAR)
-                error("bad varid: status = %d", err);
-            ELSE_NOK
-            err = ncmpi_inq_attlen(ncid, i, ATT_NAME(i,j), &len);
-            IF (err != NC_NOERR) {
-                error("%s", ncmpi_strerror(err));
-            } else {
-		IF (len != ATT_LEN(i,j))
-		    error("len not that expected");
-                ELSE_NOK
-            }
-        }
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_atttype(void)
-{
-    int ncid;
-    int i;
-    int j;
-    int err;
-    nc_type datatype;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-
-    for (i = -1; i < numVars; i++) {
-	err = ncmpi_inq_atttype(ncid, i, "noSuch", &datatype);
-	IF (err != NC_ENOTATT)
-	    error("Bad attribute name: status = %d", err);
-        ELSE_NOK
-        for (j = 0; j < NATTS(i); j++) {
-            err = ncmpi_inq_atttype(BAD_ID, i, ATT_NAME(i,j), &datatype);
-            IF (err != NC_EBADID)
-                error("bad ncid: status = %d", err);
-            ELSE_NOK
-            err = ncmpi_inq_atttype(ncid, BAD_VARID, ATT_NAME(i,j), &datatype);
-            IF (err != NC_ENOTVAR)
-                error("bad varid: status = %d", err);
-            ELSE_NOK
-            err = ncmpi_inq_atttype(ncid, i, ATT_NAME(i,j), &datatype);
-            IF (err != NC_NOERR) {
-                error("%s", ncmpi_strerror(err));
-            } else {
-		IF (datatype != ATT_TYPE(i,j))
-		    error("type not that expected");
-                ELSE_NOK
-            }
-        }
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_attname(void)
-{
-    int ncid;
-    int i;
-    int j;
-    int err;
-    char name[NC_MAX_NAME];
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-
-    for (i = -1; i < numVars; i++) {
-	err = ncmpi_inq_attname(ncid, i, BAD_ATTNUM, name);
-	IF (err != NC_ENOTATT)
-	    error("Bad attribute number: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_inq_attname(ncid, i, NATTS(i), name);
-	IF (err != NC_ENOTATT)
-	    error("Bad attribute number: status = %d", err);
-        ELSE_NOK
-        for (j = 0; j < NATTS(i); j++) {
-            err = ncmpi_inq_attname(BAD_ID, i, j, name);
-            IF (err != NC_EBADID)
-                error("bad ncid: status = %d", err);
-            ELSE_NOK
-            err = ncmpi_inq_attname(ncid, BAD_VARID, j, name);
-            IF (err != NC_ENOTVAR)
-                error("bad var id: status = %d", err);
-            ELSE_NOK
-            err = ncmpi_inq_attname(ncid, i, j, name);
-            IF (err != NC_NOERR) {
-                error("%s", ncmpi_strerror(err));
-            } else {
-		IF (strcmp(ATT_NAME(i,j), name) != 0)
-		    error("name not that expected");
-                ELSE_NOK
-            }
-        }
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
-
-int
-test_ncmpi_inq_attid(void)
-{
-    int ncid;
-    int i;
-    int j;
-    int err;
-    int attnum;
-    int nok=0;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-
-    for (i = -1; i < numVars; i++) {
-	err = ncmpi_inq_attid(ncid, i, "noSuch", &attnum);
-	IF (err != NC_ENOTATT)
-	    error("Bad attribute name: status = %d", err);
-        ELSE_NOK
-        for (j = 0; j < NATTS(i); j++) {
-            err = ncmpi_inq_attid(BAD_ID, i, ATT_NAME(i,j), &attnum);
-            IF (err != NC_EBADID)
-                error("bad ncid: status = %d", err);
-            ELSE_NOK
-            err = ncmpi_inq_attid(ncid, BAD_VARID, ATT_NAME(i,j), &attnum);
-            IF (err != NC_ENOTVAR)
-                error("bad varid: status = %d", err);
-            ELSE_NOK
-            err = ncmpi_inq_attid(ncid, i, ATT_NAME(i,j), &attnum);
-            IF (err != NC_NOERR) {
-                error("%s", ncmpi_strerror(err));
-            } else {
-		IF (attnum != j)
-		    error("attnum not that expected");
-                ELSE_NOK
-            }
-        }
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    return nok;
-}
-
diff --git a/test/nc_test/test_read.m4 b/test/nc_test/test_read.m4
new file mode 100644
index 0000000..15c75ec
--- /dev/null
+++ b/test/nc_test/test_read.m4
@@ -0,0 +1,2032 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl This file is supposed to be the same as PnetCDF's test_read.m4
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: test_read.m4 2616 2016-11-14 09:19:14Z wkliao $ */
+
+dnl
+dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
+dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types
+dnl (MPI_Offset vs. size_t), and function name substrings for external data
+dnl types.
+dnl
+
+#include <sys/types.h> /* open() */
+#include <sys/stat.h> /* open() */
+#include <fcntl.h> /* open() */
+#include <unistd.h> /* unlink(), write() */
+#include "tests.h"
+
+define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl
+
+define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl
+define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl
+define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_$1',`test_nc_$1')')dnl
+define(`APIFunc',` ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl
+
+define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, $3)', `file_open($1, $2, $3)')')dnl
+define(`FileCreate',`ifdef(`PNETCDF',`ncmpi_create(comm, $1, $2, info, $3)', `file_create($1, $2, $3)')')dnl
+define(`FileDelete',`ifdef(`PNETCDF',`ncmpi_delete($1,$2)',`nc_delete($1)')')dnl
+
+define(`VarArgs',   `ifdef(`PNETCDF',`int numVars',`void')')dnl
+define(`AttArgs',   `ifdef(`PNETCDF',`int numGatts',`void')')dnl
+define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts, int numVars',`void')')dnl
+
+define(`GetVar1', `ifdef(`PNETCDF',`ncmpi_get_var1_all($1,$2,$3,$4,$5,$6)',          `nc_get_var1($1,$2,$3,$4)')')dnl
+define(`GetVar',  `ifdef(`PNETCDF',`ncmpi_get_var_all( $1,$2,$3,$4,$5)',             `nc_get_var( $1,$2,$3)')')dnl
+define(`GetVara', `ifdef(`PNETCDF',`ncmpi_get_vara_all($1,$2,$3,$4,$5,$6,$7)',       `nc_get_vara($1,$2,$3,$4,$5)')')dnl
+define(`GetVars', `ifdef(`PNETCDF',`ncmpi_get_vars_all($1,$2,$3,$4,$5,$6,$7,$8)',    `nc_get_vars($1,$2,$3,$4,$5,$6)')')dnl
+define(`GetVarm', `ifdef(`PNETCDF',`ncmpi_get_varm_all($1,$2,$3,$4,$5,$6,$7,$8,$9)', `nc_get_varm($1,$2,$3,$4,$5,$6,$7)')')dnl
+
+/*
+ * Test APIFunc(strerror).
+ *    Try on a bad error status.
+ *    Test for each defined error status.
+ */
+int
+TestFunc(strerror)(void)
+{
+    int i;
+    const char *message, *expected_msg;
+    int nok=0;
+
+    static const struct {
+        int status;
+        const char *msg;
+    } ncerrs[] = {
+        {NC_NOERR, "No error"},
+        {NC_EBADID, "NetCDF: Not a valid ID"},
+        {NC_ENFILE, "NetCDF: Too many files open"},
+        {NC_EEXIST, "NetCDF: File exists && NC_NOCLOBBER"},
+        {NC_EINVAL, "NetCDF: Invalid argument"},
+        {NC_EPERM, "NetCDF: Write to read only"},
+        {NC_ENOTINDEFINE, "NetCDF: Operation not allowed in data mode"},
+        {NC_EINDEFINE, "NetCDF: Operation not allowed in define mode"},
+        {NC_EINVALCOORDS, "NetCDF: Index exceeds dimension bound"},
+        {NC_EMAXDIMS, "NetCDF: NC_MAX_DIMS exceeded"},
+        {NC_ENAMEINUSE, "NetCDF: String match to name in use"},
+        {NC_ENOTATT, "NetCDF: Attribute not found"},
+        {NC_EMAXATTS, "NetCDF: NC_MAX_ATTRS exceeded"},
+        {NC_EBADTYPE, "NetCDF: Not a valid data type or _FillValue type mismatch"},
+        {NC_EBADDIM, "NetCDF: Invalid dimension ID or name"},
+        {NC_EUNLIMPOS, "NetCDF: NC_UNLIMITED in the wrong index"},
+        {NC_EMAXVARS, "NetCDF: NC_MAX_VARS exceeded"},
+        {NC_ENOTVAR, "NetCDF: Variable not found"},
+        {NC_EGLOBAL, "NetCDF: Action prohibited on NC_GLOBAL varid"},
+        {NC_ENOTNC, "NetCDF: Unknown file format"},
+        {NC_ESTS, "NetCDF: In Fortran, string too short"},
+        {NC_EMAXNAME, "NetCDF: NC_MAX_NAME exceeded"},
+        {NC_EUNLIMIT, "NetCDF: NC_UNLIMITED size already in use"},
+        {NC_ENORECVARS, "NetCDF: nc_rec op when there are no record vars"},
+        {NC_ECHAR, "NetCDF: Attempt to convert between text & numbers"},
+        {NC_EEDGE, "NetCDF: Start+count exceeds dimension bound"},
+        {NC_ESTRIDE, "NetCDF: Illegal stride"},
+        {NC_EBADNAME, "NetCDF: Name contains illegal characters"},
+        {NC_ERANGE, "NetCDF: Numeric conversion not representable"},
+        {NC_ENOMEM, "NetCDF: Memory allocation (malloc) failure"},
+        {NC_EVARSIZE, "NetCDF: One or more variable sizes violate format constraints"},
+        {NC_EDIMSIZE, "NetCDF: Invalid dimension size"}
+    };
+
+    /* Try on a bad error status */
+    message = APIFunc(strerror)(-666);/* should fail */
+    expected_msg = "Unknown Error";
+    IF (strncmp(message, expected_msg, strlen(expected_msg)) != 0)
+        error("APIFunc(strerror) on bad error status returned: %s", message);
+    ELSE_NOK
+
+    /* Try on each legitimate error status */
+    for (i=0; i<LEN_OF(ncerrs); i++) {
+        const char *message = APIFunc(strerror)(ncerrs[i].status);
+        IF (strcmp(message, ncerrs[i].msg) != 0)
+            error("APIFunc(strerror)(%d) should return `%s', not `%s'",
+                  ncerrs[i].status, ncerrs[i].msg, message);
+        ELSE_NOK
+    }
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(open).
+ * If in read-only section of tests,
+ *    Try to open a non-existent netCDF file, check error return.
+ *    Open a file that is not a netCDF file, check error return.
+ *    Open a netCDF file with a bad mode argument, check error return.
+ *    Open a netCDF file with NC_NOWRITE, read-only mode, try to write, check error.
+ *    Try to open a netcdf twice, check whether returned netcdf ids different.
+ * If in writable section of tests,
+ *    Open a netCDF file with NC_WRITE mode, write something, close it.
+ * On exit, any open netCDF files are closed.
+ */
+#define NOT_NC_FILE "dummy_not_nc_file"
+int
+TestFunc(open)(void)
+{
+    int err, ncid, ncid2, nok=0;
+ifdef(`PNETCDF', ``#'if 1', ``#'if 0')
+    int fd;
+    ssize_t w_len;
+#endif
+
+    /* Try to open a nonexistent file */
+    err = FileOpen("tooth-fairy.nc", NC_NOWRITE, &ncid); /* should fail */
+
+    /* on some systems, opening an nonexisting file will actually create the
+     * file. In this case, we print the error messages on screen and move on
+     * to the next test, instead of aborting the entire test.
+     */
+    IF (err == NC_NOERR)
+        error("opening a nonexistent file expects to fail, but got NC_NOERR\n");
+ifdef(`PNETCDF',
+    `else IF (err != NC_ENOENT && err != NC_EFILE)
+        /* older version of OpenMPI and MPICH may return MPI_ERR_IO instead of
+         * MPI_ERR_NO_SUCH_FILE */
+        error("expecting NC_ENOENT or NC_EFILE but got %s", nc_err_code_name(err));
+    else {
+        nok++;
+    }', `
+`#'ifndef USE_PARALLEL
+    IF (! NC_ISSYSERR(err))
+        error("nc_open of nonexistent file should have returned system error");
+`#'endif')
+
+    /* Open a file that is not a netCDF file.  But need a portable
+     * test that also works for cross-compiles ... */
+    /* err = nc_open("nc_test.o", NC_NOWRITE, &ncid);/\* should fail *\/ */
+    /* IF (err != NC_ENOTNC) */
+    /*  error("nc_open of non-netCDF file: status = %d", err); */
+
+ifdef(`PNETCDF', ``#'if 1', ``#'if 0')
+    /* create a not-nc file */
+    fd = open(NOT_NC_FILE, O_CREAT|O_WRONLY, 0600);
+    w_len = write(fd, "0123456789abcdefghijklmnopqrstuvwxyz", 36);
+    assert(w_len >= 0);
+    close(fd);
+
+    /* Open a file that is not a netCDF file. */
+    err = FileOpen(NOT_NC_FILE, NC_NOWRITE, &ncid); /* should fail */
+    IF (err != NC_ENOTNC)
+        error("expecting NC_ENOTNC or NC_EFILE but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* delete the not-nc file */
+    unlink(NOT_NC_FILE);
+#endif
+
+    /* Open a netCDF file in read-only mode, check that write fails */
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    err = APIFunc(redef)(ncid);        /* should fail */
+    IF (err != NC_EPERM)
+        error("expecting NC_EPERM but got %s", nc_err_code_name(err));
+    /* Opened OK, see if can open again and get a different netCDF ID */
+    err = FileOpen(testfile, NC_NOWRITE, &ncid2);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    else {
+        APIFunc(close)(ncid2);
+        nok++;
+    }
+    IF (ncid2 == ncid)
+        error("netCDF IDs for first and second open calls should differ");
+
+    ifdef(`PNETCDF', `if (! read_only)')
+    {   /* tests using netCDF scratch file */
+        err = FileCreate(scratch, NC_NOCLOBBER, &ncid2);
+        IF (err != NC_NOERR)
+            error("create: %s", APIFunc(strerror)(err));
+        else
+            APIFunc(close)(ncid2);
+        err = FileOpen(scratch, NC_WRITE, &ncid2);
+        IF (err != NC_NOERR)
+            error("open: %s", APIFunc(strerror)(err));
+        else {
+            APIFunc(close)(ncid2);
+            nok++;
+        }
+        err = FileDelete(scratch, info);
+        IF (err != NC_NOERR)
+            error("remove of %s failed", scratch);
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(close).
+ *    Try to close a netCDF file twice, check whether second close fails.
+ *    Try on bad handle, check error return.
+ *    Try in define mode and data mode.
+ */
+int
+TestFunc(close)(void)
+{
+    int ncid, nok=0;
+    int err = FileOpen(testfile, NC_NOWRITE, &ncid);
+
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    /* Close a netCDF file twice, second time should fail */
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close failed: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    err = APIFunc(close)(ncid);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* Try with a bad netCDF ID */
+    err = APIFunc(close)(BAD_ID);/* should fail */
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* Close in data mode */
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close in data mode failed: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+
+    ifdef(`PNETCDF', `if (! read_only)')
+    {   /* tests using netCDF scratch file */
+        err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+        IF (err != NC_NOERR)
+            error("create: %s", APIFunc(strerror)(err));
+        err = APIFunc(close)(ncid);
+        IF (err != NC_NOERR)
+            error("close in define mode: %s", APIFunc(strerror)(err));
+        ELSE_NOK
+        err = FileDelete(scratch, info);
+        IF (err != NC_NOERR)
+            error("remove of %s failed", scratch);
+    }
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(inq)
+ *    Try on bad handle, check error return.
+ *    Try in data mode, check returned values.
+ *    Try asking for subsets of info.
+ * If in writable section of tests,
+ *    Try in define mode, after adding an unlimited dimension, variable.
+ * On exit, any open netCDF files are closed.
+ */
+int
+TestFunc(inq)(AttVarArgs)
+{
+    int ncid;
+    int ndims;                        /* number of dimensions */
+    int nvars;                        /* number of variables */
+    int ngatts;                       /* number of global attributes */
+    int recdim;                       /* id of unlimited dimension */
+    int err;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    /* Try on bad handle */
+    err = APIFunc(inq)(BAD_ID, 0, 0, 0, 0);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    err = APIFunc(inq)(ncid, &ndims, &nvars, &ngatts, &recdim);
+    IF (err != NC_NOERR)
+        error("inq: %s", APIFunc(strerror)(err));
+    else IF (ndims != NDIMS)
+        error("inq: wrong number of dimensions returned, %d", ndims);
+    else IF (nvars != numVars)
+        error("inq: wrong number of variables returned, %d", nvars);
+    else IF (ngatts != numGatts)
+        error("inq: wrong number of global atts returned, %d", ngatts);
+    else IF (recdim != RECDIM)
+        error("inq: wrong record dimension ID returned, %d", recdim);
+    ELSE_NOK
+
+    /* Inguire for no info (useless, but should still work) */
+    err = APIFunc(inq)(ncid, 0, 0, 0, 0);
+    IF (err != NC_NOERR)
+        error("inq for no info failed: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+
+    /* Inguire for subsets of info */
+    ngatts = numGatts - 1;        /* wipe out previous correct value */
+    err = APIFunc(inq)(ncid, 0, 0, &ngatts, 0);
+    IF (err != NC_NOERR)
+        error("inq for one item failed: %s", APIFunc(strerror)(err));
+    else IF (ngatts != numGatts)
+        error("inq subset: wrong number of global atts returned, %d", ngatts);
+    ELSE_NOK
+    ndims = NDIMS - 1;
+    nvars = numVars - 1;
+    err = APIFunc(inq)(ncid, &ndims, &nvars, 0, 0);
+    IF (err != NC_NOERR)
+        error("inq for two items failed: %s", APIFunc(strerror)(err));
+    else IF (ndims != NDIMS)
+        error("inq subset: wrong number of dimensions returned, %d", ndims);
+    else IF (nvars != numVars)
+        error("inq subset: wrong number of variables returned, %d", nvars);
+    ELSE_NOK
+
+    ifdef(`PNETCDF', `if (! read_only)')
+    {   /* tests using netCDF scratch file */
+        int ncid2;              /* for scratch netCDF dataset */
+
+        err = FileCreate(scratch, NC_NOCLOBBER, &ncid2);
+        IF (err != NC_NOERR) {
+            error("create: %s", APIFunc(strerror)(err));
+        } else {                /* add dim, var, gatt, check inq */
+            int ndims0;
+            int nvars0;
+            int ngatts0;
+            int recdim0;
+            err = APIFunc(enddef)(ncid2); /* enter data mode */
+            err = APIFunc(inq)(ncid2, &ndims0, &nvars0, &ngatts0, &recdim0);
+            IF (err != NC_NOERR)
+                error("inq: %s", APIFunc(strerror)(err));
+            ELSE_NOK
+            err = APIFunc(redef)(ncid2); /* enter define mode */
+            /* Check that inquire still works in define mode */
+            err = APIFunc(inq)(ncid2, &ndims, &nvars, &ngatts, &recdim);
+            IF (err != NC_NOERR)
+                error("inq in define mode: %s", APIFunc(strerror)(err));
+            else IF (ndims != ndims0)
+                error("inq in define mode: ndims wrong, %d", ndims);
+            else IF (nvars != nvars0)
+                error("inq in define mode: nvars wrong, %d", nvars);
+            else IF (ngatts != ngatts0)
+                error("inq in define mode: ngatts wrong, %d", ngatts);
+            else IF (recdim != recdim0)
+                error("inq in define mode: recdim wrong, %d", recdim);
+            ELSE_NOK
+
+            {
+                int did, vid;
+                /* Add dim, var, global att */
+                err = APIFunc(def_dim)(ncid2, "inqd", 1L, &did);
+                IF (err != NC_NOERR)
+                    error("def_dim: %s", APIFunc(strerror)(err));
+                err = APIFunc(def_var)(ncid2, "inqv", NC_FLOAT, 0, 0, &vid);
+                IF (err != NC_NOERR)
+                    error("def_var: %s", APIFunc(strerror)(err));
+            }
+            err = APIFunc(put_att_text)(ncid2, NC_GLOBAL, "inqa", 1+strlen("stuff"),
+                                   "stuff");
+            IF (err != NC_NOERR)
+                error("put_att_text: %s", APIFunc(strerror)(err));
+
+            /* Make sure APIFunc(inq) sees the additions while in define mode */
+            err = APIFunc(inq)(ncid2, &ndims, &nvars, &ngatts, &recdim);
+            IF (err != NC_NOERR)
+                error("inq in define mode: %s", APIFunc(strerror)(err));
+            else IF (ndims != ndims0 + 1)
+                error("inq in define mode: ndims wrong, %d", ndims);
+            else IF (nvars != nvars0 + 1)
+                error("inq in define mode: nvars wrong, %d", nvars);
+            else IF (ngatts != ngatts0 + 1)
+                error("inq in define mode: ngatts wrong, %d", ngatts);
+            ELSE_NOK
+            err = APIFunc(enddef)(ncid2);
+            IF (err != NC_NOERR)
+                error("enddef: %s", APIFunc(strerror)(err));
+
+            /* Make sure APIFunc(inq) stills sees additions in data mode */
+            err = APIFunc(inq)(ncid2, &ndims, &nvars, &ngatts, &recdim);
+            IF (err != NC_NOERR)
+                error("inq failed in data mode: %s", APIFunc(strerror)(err));
+            else IF (ndims != ndims0 + 1)
+                error("inq in define mode: ndims wrong, %d", ndims);
+            else IF (nvars != nvars0 + 1)
+                error("inq in define mode: nvars wrong, %d", nvars);
+            else IF (ngatts != ngatts0 + 1)
+                error("inq in define mode: ngatts wrong, %d", ngatts);
+            ELSE_NOK
+            APIFunc(close)(ncid2);
+            err = FileDelete(scratch, info);
+            IF (err != NC_NOERR)
+                error("remove of %s failed", scratch);
+        }
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_natts)(AttArgs)
+{
+    int ncid;
+    int ngatts;                        /* number of global attributes */
+    int err, nok=0;
+
+    err = APIFunc(inq_natts)(BAD_ID, &ngatts);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(inq_natts)(ncid, &ngatts);
+    IF (err != NC_NOERR)
+        error("inq_natts: %s", APIFunc(strerror)(err));
+    else IF (ngatts != numGatts)
+        error("inq_natts: wrong number of global atts returned, %d", ngatts);
+    ELSE_NOK
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_ndims)(void)
+{
+    int ncid;
+    int ndims;
+    int err;
+    int nok=0;
+
+    err = APIFunc(inq_ndims)(BAD_ID, &ndims);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(inq_ndims)(ncid, &ndims);
+    IF (err != NC_NOERR)
+        error("inq_ndims: %s", APIFunc(strerror)(err));
+    else IF (ndims != NDIMS)
+        error("inq_ndims: wrong number returned, %d", ndims);
+    ELSE_NOK
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_nvars)(VarArgs)
+{
+    int ncid;
+    int nvars;
+    int err;
+    int nok=0;
+
+    err = APIFunc(inq_nvars)(BAD_ID, &nvars);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(inq_nvars)(ncid, &nvars);
+    IF (err != NC_NOERR)
+        error("inq_nvars: %s", APIFunc(strerror)(err));
+    else IF (nvars != numVars)
+        error("inq_nvars: wrong number returned, %d", nvars);
+    ELSE_NOK
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_unlimdim)(void)
+{
+    int ncid;
+    int unlimdim;
+    int err;
+    int nok=0;
+
+    err = APIFunc(inq_unlimdim)(BAD_ID, &unlimdim);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(inq_unlimdim)(ncid, &unlimdim);
+    IF (err != NC_NOERR)
+        error("inq_unlimdim: %s", APIFunc(strerror)(err));
+    else IF (unlimdim != RECDIM)
+        error("inq_unlimdim: wrong number returned, %d", unlimdim);
+    ELSE_NOK
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_dimid)(void)
+{
+    int ncid;
+    int dimid;
+    int i;
+    int err;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(inq_dimid)(ncid, "noSuch", &dimid);
+    IF (err != NC_EBADDIM)
+        error("expecting NC_EBADDIM but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    for (i = 0; i < NDIMS; i++) {
+        err = APIFunc(inq_dimid)(BAD_ID, dim_name[i], &dimid);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_dimid)(ncid, dim_name[i], &dimid);
+        IF (err != NC_NOERR)
+            error("inq_dimid: %s", APIFunc(strerror)(err));
+        else IF (dimid != i)
+            error("expected %d, got %d", i, dimid);
+        ELSE_NOK
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_dim)(void)
+{
+    int ncid;
+    int i;
+    int err;
+    char name[NC_MAX_NAME];
+    IntType length;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    for (i = 0; i < NDIMS; i++) {
+        err = APIFunc(inq_dim)(BAD_ID, i, name, &length);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_dim)(ncid, BAD_DIMID, name, &length);
+        IF (err != NC_EBADDIM)
+            error("expecting NC_EBADDIM but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_dim)(ncid, i, 0, 0);
+        IF (err != NC_NOERR)
+            error("inq_dim: %s", APIFunc(strerror)(err));
+        ELSE_NOK
+        err = APIFunc(inq_dim)(ncid, i, name, &length);
+        IF (err != NC_NOERR)
+            error("inq_dim: %s", APIFunc(strerror)(err));
+        else IF (strcmp(dim_name[i],name))
+            error("name expected: %s, got: %s",dim_name[i],name);
+        else IF (dim_len[i] != length)
+            error("size expected: %d, got: %d",dim_len[i],length);
+        ELSE_NOK
+        err = APIFunc(inq_dim)(ncid, i, name, 0);
+        IF (err != NC_NOERR)
+            error("inq_dim: %s", APIFunc(strerror)(err));
+        else IF (strcmp(dim_name[i],name))
+            error("name expected: %s, got: %s",dim_name[i],name);
+        ELSE_NOK
+        err = APIFunc(inq_dim)(ncid, i, 0, &length);
+        IF (err != NC_NOERR)
+            error("inq_dim: %s", APIFunc(strerror)(err));
+        else IF (dim_len[i] != length)
+            error("size expected: %d, got: %d",dim_len[i],length);
+        ELSE_NOK
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_dimlen)(void)
+{
+    int ncid;
+    int i;
+    int err;
+    IntType  length;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    for (i = 0; i < NDIMS; i++) {
+        err = APIFunc(inq_dimlen)(BAD_ID, i, &length);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_dimlen)(ncid, BAD_DIMID, &length);
+        IF (err != NC_EBADDIM)
+            error("expecting NC_EBADDIM but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_dimlen)(ncid, i, &length);
+        IF (err != NC_NOERR)
+            error("inq_dimlen: %s", APIFunc(strerror)(err));
+        else IF (dim_len[i] != length)
+            error("size expected: %d, got: %d",dim_len[i],length);
+        ELSE_NOK
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_dimname)(void)
+{
+    int ncid;
+    int i;
+    int err;
+    char name[NC_MAX_NAME];
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    for (i = 0; i < NDIMS; i++) {
+        err = APIFunc(inq_dimname)(BAD_ID, i, name);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_dimname)(ncid, BAD_DIMID, name);
+        IF (err != NC_EBADDIM)
+            error("expecting NC_EBADDIM but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_dimname)(ncid, i, name);
+        IF (err != NC_NOERR)
+            error("inq_dimname: %s", APIFunc(strerror)(err));
+        else IF (strcmp(dim_name[i],name))
+            error("name expected: %s, got: %s",dim_name[i],name);
+        ELSE_NOK
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_varid)(VarArgs)
+{
+    int ncid;
+    int varid;
+    int i;
+    int err;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(inq_varid)(ncid, "noSuch", &varid);
+    IF (err != NC_ENOTVAR)
+        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    for (i = 0; i < numVars; i++) {
+        err = APIFunc(inq_varid)(BAD_ID, var_name[i], &varid);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_varid)(ncid, var_name[i], &varid);
+        IF (err != NC_NOERR)
+            error("inq_varid: %s", APIFunc(strerror)(err));
+        else IF (varid != i)
+            error("expected %d, got %d", i, varid);
+        ELSE_NOK
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_var)(VarArgs)
+{
+    int ncid;
+    int i;
+    int err;
+    char name[NC_MAX_NAME];
+    nc_type datatype;
+    int ndims;
+    int dimids[MAX_RANK];
+    int natts;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    for (i = 0; i < numVars; i++) {
+        err = APIFunc(inq_var)(BAD_ID, i, name, &datatype, &ndims, dimids, &natts);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_var)(ncid,BAD_VARID,name,&datatype,&ndims,dimids,&natts);
+        IF (err != NC_ENOTVAR)
+            error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_var)(ncid, i, 0, 0, 0, 0, 0);
+        IF (err != NC_NOERR)
+            error("inq_var: %s", APIFunc(strerror)(err));
+        ELSE_NOK
+        err = APIFunc(inq_var)(ncid, i, name, &datatype, &ndims, dimids, &natts);
+        IF (err != NC_NOERR)
+            error("inq_var: %s", APIFunc(strerror)(err));
+        else IF (strcmp(var_name[i],name))
+            error("name expected: %s, got: %s",var_name[i],name);
+        else IF (var_type[i] != datatype)
+            error("type expected: %d, got: %d",var_type[i],datatype);
+        else IF (var_rank[i] != ndims)
+            error("ndims expected: %d, got: %d",var_rank[i],ndims);
+        else IF (!int_vec_eq(var_dimid[i],dimids,ndims))
+            error("unexpected dimid");
+        else IF (var_natts[i] != natts)
+            error("natts expected: %d, got: %d",var_natts[i],natts);
+        ELSE_NOK
+        err = APIFunc(inq_var)(ncid, i, name, 0, 0, 0, 0);
+        IF (err != NC_NOERR)
+            error("inq_var: %s", APIFunc(strerror)(err));
+        else IF (strcmp(var_name[i],name))
+            error("name expected: %s, got: %s",var_name[i],name);
+        ELSE_NOK
+        err = APIFunc(inq_var)(ncid, i, 0, &datatype, 0, 0, 0);
+        IF (err != NC_NOERR)
+            error("inq_var: %s", APIFunc(strerror)(err));
+        else IF (var_type[i] != datatype)
+            error("type expected: %d, got: %d",var_type[i],datatype);
+        ELSE_NOK
+        err = APIFunc(inq_var)(ncid, i, 0, 0, &ndims, 0, 0);
+        IF (err != NC_NOERR)
+            error("inq_var: %s", APIFunc(strerror)(err));
+        else IF (var_rank[i] != ndims)
+            error("ndims expected: %d, got: %d",var_rank[i],ndims);
+        ELSE_NOK
+        err = APIFunc(inq_var)(ncid, i, 0, 0, 0, dimids, 0);
+        IF (err != NC_NOERR)
+            error("inq_var: %s", APIFunc(strerror)(err));
+        else IF (!int_vec_eq(var_dimid[i],dimids,ndims))
+            error("unexpected dimid");
+        ELSE_NOK
+        err = APIFunc(inq_var)(ncid, i, 0, 0, 0, 0, &natts);
+        IF (err != NC_NOERR)
+            error("inq_var: %s", APIFunc(strerror)(err));
+        else IF (var_natts[i] != natts)
+            error("natts expected: %d, got: %d",var_natts[i],natts);
+        ELSE_NOK
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_vardimid)(VarArgs)
+{
+    int ncid;
+    int i;
+    int err;
+    int dimids[MAX_RANK];
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    for (i = 0; i < numVars; i++) {
+        err = APIFunc(inq_vardimid)(BAD_ID, i, dimids);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_vardimid)(ncid, BAD_VARID, dimids);
+        IF (err != NC_ENOTVAR)
+            error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_vardimid)(ncid, i, dimids);
+        IF (err != NC_NOERR)
+            error("inq_vardimid: %s", APIFunc(strerror)(err));
+        else IF (!int_vec_eq(var_dimid[i], dimids, var_rank[i]))
+            error("unexpected dimid");
+        ELSE_NOK
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_varname)(VarArgs)
+{
+    int ncid;
+    int i;
+    int err;
+    char name[NC_MAX_NAME];
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    for (i = 0; i < numVars; i++) {
+        err = APIFunc(inq_varname)(BAD_ID, i, name);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        nok++;
+        err = APIFunc(inq_varname)(ncid, BAD_VARID, name);
+        IF (err != NC_ENOTVAR)
+            error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_varname)(ncid, i, name);
+        IF (err != NC_NOERR)
+            error("inq_varname: %s", APIFunc(strerror)(err));
+        else IF (strcmp(var_name[i],name))
+            error("name expected: %s, got: %s",var_name[i],name);
+        ELSE_NOK
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_varnatts)(AttVarArgs)
+{
+    int ncid;
+    int i;
+    int err;
+    int natts;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    for (i = -1; i < numVars; i++) {
+        err = APIFunc(inq_varnatts)(BAD_ID, i, &natts);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_varnatts)(ncid, BAD_VARID, &natts);
+        IF (err != NC_ENOTVAR)
+            error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_varnatts)(ncid, VARID(i), &natts);
+        IF (err != NC_NOERR)
+            error("inq_varnatts: %s", APIFunc(strerror)(err));
+        else IF (NATTS(i) != natts)
+            error("natts expected: %d, got: %d",NATTS(i),natts);
+        ELSE_NOK
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_varndims)(VarArgs)
+{
+    int ncid;
+    int i;
+    int err;
+    int ndims;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    for (i = 0; i < numVars; i++) {
+        err = APIFunc(inq_varndims)(BAD_ID, i, &ndims);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_varndims)(ncid, BAD_VARID, &ndims);
+        IF (err != NC_ENOTVAR)
+            error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_varndims)(ncid, i, &ndims);
+        IF (err != NC_NOERR)
+            error("inq_varndims: %s", APIFunc(strerror)(err));
+        else IF (var_rank[i] != ndims)
+            error("ndims expected: %d, got: %d",var_rank[i],ndims);
+        ELSE_NOK
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_vartype)(VarArgs)
+{
+    int ncid;
+    int i;
+    int err;
+    nc_type datatype;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    for (i = 0; i < numVars; i++) {
+        err = APIFunc(inq_vartype)(BAD_ID, i, &datatype);
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_vartype)(ncid, BAD_VARID, &datatype);
+        IF (err != NC_ENOTVAR)
+            error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_vartype)(ncid, i, &datatype);
+        IF (err != NC_NOERR)
+            error("inq_vartype: %s", APIFunc(strerror)(err));
+        else IF (var_type[i] != datatype)
+            error("type expected: %d, got: %d", var_type[i], datatype);
+        ELSE_NOK
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+/*
+ * Test GetVar1
+ */
+int
+TestFunc(get_var1)(VarArgs)
+{
+    int ncid;
+    int i;
+    int err;
+    double expect;
+    int nok = 0;                /* count of valid comparisons */
+    double buf[1];              /* (void *) buffer */
+    double value[1];
+    IntType j, index[MAX_RANK];
+    ifdef(`PNETCDF', `MPI_Datatype datatype;')
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR) error("open: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = GetVar1(BAD_ID, 0, NULL, NULL, 0, MPI_DATATYPE_NULL);
+    IF (err != NC_EBADID) EXPECT_ERR(NC_EBADID, err)
+
+    /* check if can detect a bad variable ID */
+    err = GetVar1(ncid, BAD_VARID, NULL, NULL, 0, MPI_DATATYPE_NULL);
+    IF (err != NC_ENOTVAR) EXPECT_ERR(NC_ENOTVAR, err)
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = GetVar1(BAD_ID, i, NULL, value, 1, MPI_DATATYPE_NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
+
+ifdef(`PNETCDF',`dnl
+        err = GetVar1(ncid, i, NULL, value, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS */
+        for (j = 0; j < var_rank[i]; j++) {
+            index[j] = var_shape[i][j];
+            err = GetVar1(ncid, i, index, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            index[j] = 0;
+        }
+        err = GetVar1(ncid, i, index, value, 1, datatype);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+
+        /* check if the contents are supposed to be */
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != 0) error("error in toMixedBase");
+            expect = hash( var_type[i], var_rank[i], index );
+            err = GetVar1(ncid, i, index, buf, 1, datatype);
+            IF (err != NC_NOERR)
+                EXPECT_ERR(NC_NOERR, err)
+            ELSE_NOK
+            err = nc2dbl( var_type[i], buf, &value[0]);
+            IF (err)
+                error("error in nc2dbl");
+            if (inRange(expect,var_type[i])) {
+                IF (!equal2(value[0],expect,var_type[i]))
+                    error("expected: %G, got: %G", expect, value[0]);
+                ELSE_NOK
+            }
+        }
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+/*
+ * Test GetVara
+ * Choose a random point dividing each dim into 2 parts
+ * Get 2^rank (nslabs) slabs so defined
+ * Each get overwrites buffer, so check after each get.
+ */
+int
+TestFunc(get_vara)(VarArgs)
+{
+    int ncid, d, i, k, err, nslabs;
+    int nok = 0;      /* count of valid comparisons */
+    IntType j, nels;
+    IntType start[MAX_RANK];
+    IntType edge[MAX_RANK];
+    IntType index[MAX_RANK];
+    IntType mid[MAX_RANK];
+    ifdef(`PNETCDF', `MPI_Datatype datatype;')
+    double buf[MAX_NELS];        /* (void *) buffer */
+    double expect;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = GetVara(BAD_ID, 0, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL);
+    IF (err != NC_EBADID) EXPECT_ERR(NC_EBADID, err)
+
+    /* check if can detect a bad variable ID */
+    err = GetVara(ncid, BAD_VARID, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL);
+    IF (err != NC_ENOTVAR) EXPECT_ERR(NC_ENOTVAR, err)
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = GetVara(BAD_ID, i, NULL, NULL, buf, 1, MPI_DATATYPE_NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
+
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+        }
+
+ifdef(`PNETCDF',`dnl
+        err = GetVara(ncid, i, NULL, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+        err = GetVara(ncid, i, start, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
+        ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS, first when edge[*] > 0 */
+        for (j = 0; j < var_rank[i]; j++) {
+            index[j] = var_shape[i][j];
+            err = GetVara(ncid, i, index, edge, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            index[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = GetVara(ncid, i, start, edge, buf, 1, datatype);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            ELSE_NOK
+            edge[j] = 1;
+        }
+
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = GetVara(ncid, i, start, edge, buf, 0, datatype);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1;  /* out of boundary check */
+            err = GetVara(ncid, i, start, edge, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
+        err = GetVara(ncid, i, start, edge, buf, 1, datatype);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        for (k = 0; k < nslabs; k++) {
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                nels *= edge[j];
+            }
+            err = GetVara(ncid, i, start, edge, buf, nels, datatype);
+            IF (err != NC_NOERR)
+                EXPECT_ERR(NC_NOERR, err)
+            ELSE_NOK
+
+            for (j = 0; j < nels; j++) {
+                double got;
+                char *p = (char *) buf;
+                p += j * (IntType)nctypelen(var_type[i]);
+                err = nc2dbl( var_type[i], p, & got );
+                IF (err) error("error in nc2dbl");
+                err = toMixedBase(j, var_rank[i], edge, index);
+                IF (err != 0) error("error in toMixedBase");
+                for (d = 0; d < var_rank[i]; d++)
+                    index[d] += start[d];
+                expect = hash(var_type[i], var_rank[i], index);
+                if (inRange(expect,var_type[i])) {
+                    IF (!equal2(got,expect,var_type[i])) {
+                        error("buf read not that expected");
+                        if (verbose) {
+                            error("\n");
+                            error("varid: %d, ", i);
+                            error("var_name: %s, ", var_name[i]);
+                            error("element number: %d ", j);
+                            error("expect: %g", expect);
+                            error("got: %g", got);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+/*
+ * Test GetVars
+ * Choose a random point dividing each dim into 2 parts
+ * Get 2^rank (nslabs) slabs so defined
+ * Each get overwrites buffer, so check after each get.
+ */
+int
+TestFunc(get_vars)(VarArgs)
+{
+    int ncid;
+    int d;
+    int i;
+    int k;
+    int err;
+    int nslabs;
+    PTRDType nstarts;   /* number of different starts */
+    int nok = 0;        /* total count of valid comparisons */
+    int n;              /* count of valid comparisons within var */
+    IntType j, m, nels;
+    IntType start[MAX_RANK];
+    IntType edge[MAX_RANK];
+    IntType index[MAX_RANK];
+    IntType index2[MAX_RANK];
+    IntType mid[MAX_RANK];
+    IntType count[MAX_RANK];
+    IntType sstride[MAX_RANK];
+    PTRDType stride[MAX_RANK];
+    ifdef(`PNETCDF', `MPI_Datatype datatype;')
+    double buf[MAX_NELS];     /* (void *) buffer */
+    char *p;                  /* (void *) pointer */
+    double expect;
+    double got;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = GetVars(BAD_ID, 0, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL);
+    IF (err != NC_EBADID) EXPECT_ERR(NC_EBADID, err)
+
+    /* check if can detect a bad variable ID */
+    err = GetVars(ncid, BAD_VARID, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL);
+    IF (err != NC_ENOTVAR) EXPECT_ERR(NC_ENOTVAR, err)
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = GetVars(BAD_ID, i, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
+
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+
+ifdef(`PNETCDF',`dnl
+        err = GetVars(ncid, i, NULL, NULL, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+        err = GetVars(ncid, i, start, NULL, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
+        ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS, first when edge[*] > 0 */
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j];
+            err = GetVars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;
+            err = GetVars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;
+            err = GetVars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
+        }
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = GetVars(ncid, i, start, edge, stride, buf, 0, datatype);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1;  /* out of boundary check */
+            err = GetVars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
+        err = GetVars(ncid, i, start, edge, stride, buf, 1, datatype);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        n = 0;
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                stride[j] = (PTRDType)sstride[j];
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != 0) error("error in toMixedBase");
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * (IntType)stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+ */
+                err = GetVars(ncid, i, index, count, stride, buf, nels, datatype);
+                IF (err != NC_NOERR)
+                    error("%s", APIFunc(strerror)(err));
+                ELSE_NOK
+
+                for (j = 0; j < nels; j++) {
+                    p = (char *) buf;
+                    p += j * (IntType)nctypelen(var_type[i]);
+                    err = nc2dbl( var_type[i], p, & got );
+                    IF (err != NC_NOERR)
+                        error("error in nc2dbl");
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != 0) error("error in toMixedBase");
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * (IntType)stride[d];
+                    expect = hash(var_type[i], var_rank[i], index2);
+                    if (inRange(expect,var_type[i])) {
+                        IF (!equal2(got,expect,var_type[i])) {
+                            error("buf read not that expected");
+                            if (verbose) {
+                                error("\n");
+                                error("varid: %d, ", i);
+                                error("var_name: %s, ", var_name[i]);
+                                error("element number: %d ", j);
+                                error("expect: %g, ", expect);
+                                error("got: %g ", got);
+                            }
+                        }
+                        ELSE_NOK
+                    }
+                    n++;
+                }
+            }
+        }
+        IF (n != var_nels[i]) {
+            error("count != nels");
+            if (verbose) {
+                error("\n");
+                error("varid: %d, ", i);
+                error("var_name: %s, ", var_name[i]);
+                error("count: %d, ", n);
+                error("nels: %d ", var_nels[i]);
+            }
+        }
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+/*
+ * Test GetVarm
+ * Choose a random point dividing each dim into 2 parts
+ * Get 2^rank (nslabs) slabs so defined
+ * Choose random stride from 1 to edge
+ * Buffer should end up being bit image of external variable.
+ * So all gets for a variable store in different elements of buffer
+ */
+int
+TestFunc(get_varm)(VarArgs)
+{
+    int ncid;
+    int i;
+    int k;
+    int err;
+    int nslabs;
+    PTRDType nstarts;   /* number of different starts */
+    int nok = 0;        /* total count of valid comparisons */
+    IntType j, m, nels;
+    IntType start[MAX_RANK];
+    IntType edge[MAX_RANK];
+    IntType index[MAX_RANK];
+    IntType mid[MAX_RANK];
+    IntType count[MAX_RANK];
+    IntType sstride[MAX_RANK];
+    PTRDType stride[MAX_RANK];
+    PTRDType imap[MAX_RANK];
+    PTRDType imap2[MAX_RANK];
+    ifdef(`PNETCDF', `MPI_Datatype datatype;')
+    double buf[MAX_NELS];        /* (void *) buffer */
+    char *p;                     /* (void *) pointer */
+    double expect;
+    double got;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = GetVarm(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL);
+    IF (err != NC_EBADID) EXPECT_ERR(NC_EBADID, err)
+
+    /* check if can detect a bad variable ID */
+    err = GetVarm(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL, 0, MPI_DATATYPE_NULL);
+    IF (err != NC_ENOTVAR) EXPECT_ERR(NC_ENOTVAR, err)
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        /* check if can detect a bad file ID */
+        err = GetVarm(BAD_ID, i, NULL, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
+
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+            imap[j] = 1;
+        }
+
+ifdef(`PNETCDF',`dnl
+        err = GetVarm(ncid, i, NULL, NULL, NULL, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+        err = GetVarm(ncid, i, start, NULL, NULL, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
+        ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS, first when edge[*] > 0 */
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j];
+            err = GetVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;
+            err = GetVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDGE, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;
+            err = GetVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
+        }
+        /* Check non-scalars for correct error returned even when there is
+         * nothing to get (edge[j]==0) */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = GetVarm(ncid, i, start, edge, stride, imap, buf, 0, datatype);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1;  /* out of boundary check */
+            err = GetVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
+        err = GetVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+        IF (err != NC_NOERR)
+            EXPECT_ERR(NC_NOERR, err)
+        ELSE_NOK
+
+        if (var_rank[i] > 0) {
+            int jj = var_rank[i] - 1;
+            /* imap[jj] = nctypelen(var_type[i]); */
+            imap[jj] = 1; /* in numbers of elements */
+            for (; jj > 0; jj--)
+                imap[jj-1] = imap[jj] * (PTRDType)var_shape[i][jj];
+        }
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                stride[j] = (PTRDType)sstride[j];
+                imap2[j] = imap[j] * stride[j];
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                if (var_rank[i] == 0 && i%2 ) {
+                    err = GetVarm(ncid, i, NULL, NULL, NULL, NULL, buf, var_nels[i], datatype);
+                } else {
+                    err = toMixedBase(m, var_rank[i], sstride, index);
+                    IF (err != 0) error("error in toMixedBase");
+                    nels = 1;
+                    for (j = 0; j < var_rank[i]; j++) {
+                        count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j];
+                        index[j] += start[j];
+                        nels *= count[j];
+                    }
+                    /* Random choice of forward or backward */
+/* TODO
+                    if ( roll(2) ) {
+                        for (j = 0; j < var_rank[i]; j++) {
+                            index[j] += (count[j] - 1) * (IntType)stride[j];
+                            stride[j] = -stride[j];
+                        }
+                    }
+ */
+                    j = fromMixedBase(var_rank[i], index, var_shape[i]);
+                    p = (char *) buf + j * (IntType)nctypelen(var_type[i]);
+                    err = GetVarm(ncid, i, index, count, stride, imap2, p, nels, datatype);
+                }
+                IF (err != NC_NOERR)
+                    error("%s", APIFunc(strerror)(err));
+                ELSE_NOK
+            }
+        }
+        p = (char *) buf;
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != 0) error("error in toMixedBase");
+            expect = hash( var_type[i], var_rank[i], index);
+            err = nc2dbl( var_type[i], p, & got );
+            IF (err != NC_NOERR)
+                error("error in nc2dbl");
+            if (inRange(expect,var_type[i])) {
+                IF (!equal2(got,expect,var_type[i])) {
+                    error("buf read not that expected");
+                    if (verbose) {
+                        error("\n");
+                        error("varid: %d, ", i);
+                        error("var_name: %s, ", var_name[i]);
+                        error("element number: %d ", j);
+                        error("expect: %g, ", expect);
+                        error("got: %g ", got);
+                    }
+                }
+                ELSE_NOK
+            }
+            p += nctypelen(var_type[i]);
+        }
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(get_att)(AttVarArgs)
+{
+    int ncid;
+    int i;
+    int j;
+    IntType k;
+    int err;
+    double buf[MAX_NELS];        /* (void *) buffer */
+    char *p;                     /* (void *) pointer */
+    double expect;
+    double got;
+    int nok = 0;      /* count of valid comparisons */
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    for (i = -1; i < numVars; i++) {
+        for (j = 0; j < NATTS(i); j++) {
+            err = APIFunc(get_att)(BAD_ID, i, ATT_NAME(i,j), buf);
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(get_att)(ncid, BAD_VARID, ATT_NAME(i,j), buf);
+            IF (err != NC_ENOTVAR)
+                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(get_att)(ncid, i, "noSuch", buf);
+            IF (err != NC_ENOTATT)
+                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(get_att)(ncid, i, ATT_NAME(i,j), buf);
+            IF (err != NC_NOERR) {
+                error("%s", APIFunc(strerror)(err));
+            } else {
+                nok++;
+                for (k = 0; k < ATT_LEN(i,j); k++) {
+                    expect = hash(ATT_TYPE(i,j), -1, &k);
+                    p = (char *) buf;
+                    p += k * (IntType)nctypelen(ATT_TYPE(i,j));
+                    err = nc2dbl( ATT_TYPE(i,j), p, &got );
+                    IF (err != NC_NOERR)
+                        error("error in nc2dbl");
+                    if (inRange(expect,ATT_TYPE(i,j))) {
+                        IF (!equal2(got,expect,ATT_TYPE(i,j))) {
+                            error("buf read not that expected");
+                            if (verbose) {
+                                error("\n");
+                                error("varid: %d, ", i);
+                                error("var_name: %s, ",
+                                        i >= 0 ? var_name[i] : "Global");
+                                error("att_name: %s, ", ATT_NAME(i,j));
+                                error("element number: %d\n", k);
+                                error("expect: %-23.16e\n", expect);
+                                error("   got: %-23.16e", got);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_att)(AttVarArgs)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    nc_type t;
+    IntType n;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    for (i = -1; i < numVars; i++) {
+        for (j = 0; j < NATTS(i); j++) {
+            err = APIFunc(inq_att)(BAD_ID, i, ATT_NAME(i,j), &t, &n);
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_att)(ncid, BAD_VARID, ATT_NAME(i,j), &t, &n);
+            IF (err != NC_ENOTVAR)
+                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_att)(ncid, i, "noSuch", &t, &n);
+            IF (err != NC_ENOTATT)
+                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_att)(ncid, i, ATT_NAME(i,j), &t, &n);
+            IF (err != NC_NOERR) {
+                error("%s", APIFunc(strerror)(err));
+            } else {
+                IF (t != ATT_TYPE(i,j))
+                    error("type not that expected");
+                ELSE_NOK
+                IF (n != ATT_LEN(i,j))
+                    error("length not that expected");
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_attlen)(AttVarArgs)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    IntType len;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    for (i = -1; i < numVars; i++) {
+        err = APIFunc(inq_attlen)(ncid, i, "noSuch", &len);
+        IF (err != NC_ENOTATT)
+            error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        for (j = 0; j < NATTS(i); j++) {
+            err = APIFunc(inq_attlen)(BAD_ID, i, ATT_NAME(i,j), &len);
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_attlen)(ncid, BAD_VARID, ATT_NAME(i,j), &len);
+            IF (err != NC_ENOTVAR)
+                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_attlen)(ncid, i, ATT_NAME(i,j), &len);
+            IF (err != NC_NOERR) {
+                error("%s", APIFunc(strerror)(err));
+            } else {
+                IF (len != ATT_LEN(i,j))
+                    error("len not that expected");
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_atttype)(AttVarArgs)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    nc_type datatype;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    for (i = -1; i < numVars; i++) {
+        err = APIFunc(inq_atttype)(ncid, i, "noSuch", &datatype);
+        IF (err != NC_ENOTATT)
+            error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        for (j = 0; j < NATTS(i); j++) {
+            err = APIFunc(inq_atttype)(BAD_ID, i, ATT_NAME(i,j), &datatype);
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_atttype)(ncid, BAD_VARID, ATT_NAME(i,j), &datatype);
+            IF (err != NC_ENOTVAR)
+                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_atttype)(ncid, i, ATT_NAME(i,j), &datatype);
+            IF (err != NC_NOERR) {
+                error("%s", APIFunc(strerror)(err));
+            } else {
+                IF (datatype != ATT_TYPE(i,j))
+                    error("type not that expected");
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_attname)(AttVarArgs)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    char name[NC_MAX_NAME];
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    for (i = -1; i < numVars; i++) {
+        err = APIFunc(inq_attname)(ncid, i, BAD_ATTNUM, name);
+        IF (err != NC_ENOTATT)
+            error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(inq_attname)(ncid, i, NATTS(i), name);
+        IF (err != NC_ENOTATT)
+            error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        for (j = 0; j < NATTS(i); j++) {
+            err = APIFunc(inq_attname)(BAD_ID, i, j, name);
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_attname)(ncid, BAD_VARID, j, name);
+            IF (err != NC_ENOTVAR)
+                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_attname)(ncid, i, j, name);
+            IF (err != NC_NOERR) {
+                error("%s", APIFunc(strerror)(err));
+            } else {
+                IF (strcmp(ATT_NAME(i,j), name) != 0)
+                    error("name not that expected");
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
+
+int
+TestFunc(inq_attid)(AttVarArgs)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    int attnum;
+    int nok=0;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    for (i = -1; i < numVars; i++) {
+        err = APIFunc(inq_attid)(ncid, i, "noSuch", &attnum);
+        IF (err != NC_ENOTATT)
+            error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        for (j = 0; j < NATTS(i); j++) {
+            err = APIFunc(inq_attid)(BAD_ID, i, ATT_NAME(i,j), &attnum);
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_attid)(ncid, BAD_VARID, ATT_NAME(i,j), &attnum);
+            IF (err != NC_ENOTVAR)
+                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(inq_attid)(ncid, i, ATT_NAME(i,j), &attnum);
+            IF (err != NC_NOERR) {
+                error("%s", APIFunc(strerror)(err));
+            } else {
+                IF (attnum != j)
+                    error("attnum not that expected");
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    return nok;
+}
+
diff --git a/test/nc_test/test_write.c b/test/nc_test/test_write.c
deleted file mode 100644
index 604601e..0000000
--- a/test/nc_test/test_write.c
+++ /dev/null
@@ -1,2185 +0,0 @@
-/*
- *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
- *  See COPYRIGHT notice in top-level directory.
- *
- *  $Id: test_write.c 2289 2016-01-02 08:26:40Z wkliao $
- */
-
-#include "tests.h"
-#include "math.h"
-
-
-/*
- * Test ncmpi_create
- *    For mode in NC_NOCLOBBER|extra_flags, NC_CLOBBER, info do:
- *       create netcdf file 'scratch.nc' with no data, close it
- *       test that it can be opened, do ncmpi_inq to check nvars = 0, etc.
- *    Try again in NC_NOCLOBBER|extra_flags mode, check error return
- * On exit, delete this file
- */
-int
-test_ncmpi_create(void)
-{
-    int clobber; /* 0 for NC_NOCLOBBER|extra_flags, 1 for NC_CLOBBER, info */
-    int err;
-    int ncid;
-    int ndims;   /* number of dimensions */
-    int nvars;   /* number of variables */
-    int ngatts;  /* number of global attributes */
-    int recdim;  /* id of unlimited dimension */
-    int nok=0;
-
-    for (clobber = 0; clobber < 2; clobber++) {
-	err = ncmpi_create(comm, scratch, clobber ? NC_CLOBBER|extra_flags : NC_NOCLOBBER, info, &ncid);
-	IF (err != NC_NOERR)
-	    error("ncmpi_create: %s", ncmpi_strerror(err));
-        ELSE_NOK
-	err = ncmpi_close(ncid);
-	IF (err != NC_NOERR)
-	    error("ncmpi_close: %s", ncmpi_strerror(err));
-	err = ncmpi_open(comm, scratch, NC_NOWRITE, info, &ncid);
-	IF (err != NC_NOERR)
-	    error("ncmpi_open: %s", ncmpi_strerror(err));
-	err = ncmpi_inq(ncid, &ndims, &nvars, &ngatts, &recdim);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq: %s", ncmpi_strerror(err));
-	else IF (ndims != 0)
-	    error("ncmpi_inq: wrong number of dimensions returned, %d", ndims);
-	else IF (nvars != 0)
-	    error("ncmpi_inq: wrong number of variables returned, %d", nvars);
-	else IF (ngatts != 0)
-	    error("ncmpi_inq: wrong number of global atts returned, %d", ngatts);
-	else IF (recdim != -1)
-	    error("ncmpi_inq: wrong record dimension ID returned, %d", recdim);
-        ELSE_NOK
-	err = ncmpi_close(ncid);
-	IF (err != NC_NOERR)
-	    error("ncmpi_close: %s", ncmpi_strerror(err));
-    }
-
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_EEXIST)
-	error("attempt to overwrite file: status = %d", err);
-    ELSE_NOK
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-	error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_redef 
- * (In fact also tests ncmpi_enddef - called from test_ncmpi_enddef)
- *    BAD_ID
- *    attempt redef (error) & enddef on read-only file
- *    create file, define dims & vars. 
- *    attempt put var (error)
- *    attempt redef (error) & enddef.
- *    put vars
- *    attempt def new dims (error)
- *    redef
- *    def new dims, vars.
- *    put atts
- *    enddef
- *    put vars
- *    close
- *    check file: vars & atts
- */
-int
-test_ncmpi_redef(void)
-{
-    int ncid;                   /* netcdf id */
-    /* used to force effective test of ncio->move() in redef */
-    size_t sizehint = 8192;
-    int dimid;         /* dimension id */
-    int varid;         /* variable id */
-    int varid1;        /* variable id */
-    int nok=0, err;
-    const char * title = "Not funny";
-    double var;
-    char name[NC_MAX_NAME];
-    MPI_Offset length;
-
-    /* BAD_ID tests */
-    err = ncmpi_redef(BAD_ID);
-    IF (err != NC_EBADID)
-	error("bad ncid: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_enddef(BAD_ID);
-    IF (err != NC_EBADID)
-	error("bad ncid: status = %d", err);
-    ELSE_NOK
-
-    /* read-only tests */
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_redef(ncid);
-    IF (err != NC_EPERM)
-	error("ncmpi_redef in NC_NOWRITE, info mode: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_ENOTINDEFINE)
-	error("ncmpi_endfef in NC_NOWRITE, info mode: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    /* tests using scratch file */
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    /* err = ncmpi__create(scratch, NC_NOCLOBBER|extra_flags, 0, &sizehint, &ncid); */
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    /* limit for ncio implementations which which have infinite chunksize */
-    if(sizehint > 32768)
-	sizehint = 16384;
-    def_dims(ncid);
-    def_vars(ncid);
-    put_atts(ncid);
-    err = ncmpi_inq_varid(ncid, "d", &varid);
-    IF (err != NC_NOERR) 
-	error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
-    var = 1.0;
-    err = ncmpi_begin_indep_data(ncid);
-    IF (err != NC_EINDEFINE)
-        error("ncmpi_begin_indep_data... in define mode: status = %d", err);
-    err = ncmpi_put_var1_double(ncid, varid, NULL, &var);
-    IF (err != NC_EINDEFINE)
-        error("ncmpi_put_var... in define mode: status = %d", err);
-    err = ncmpi_end_indep_data(ncid);
-    IF (err != NC_ENOTINDEP)
-        error("ncmpi_end_indep_data... not in indep mode: status = %d", err);
-    err = ncmpi_redef(ncid);
-    IF (err != NC_EINDEFINE)
-        error("ncmpi_redef in define mode: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    put_vars(ncid);
-    err = ncmpi_def_dim(ncid, "abc", sizehint, &dimid);
-    IF (err != NC_ENOTINDEFINE)
-        error("ncmpi_def_dim in define mode: status = %d", err);
-    err = ncmpi_redef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_redef: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    err = ncmpi_set_fill(ncid, NC_NOFILL, NULL);
-    IF (err != NC_NOERR)
-        error("ncmpi_set_fill: %s", ncmpi_strerror(err));
-    err = ncmpi_def_dim(ncid, "abc", sizehint, &dimid);
-    IF (err != NC_NOERR)
-        error("ncmpi_def_dim: %s", ncmpi_strerror(err));
-    err = ncmpi_def_var(ncid, "abcScalar", NC_INT, 0, NULL, &varid);
-    IF (err != NC_NOERR)
-        error("ncmpi_def_var: %s", ncmpi_strerror(err));
-    err = ncmpi_def_var(ncid, "abc", NC_INT, 1, &dimid, &varid1);
-    IF (err != NC_NOERR)
-        error("ncmpi_def_var: %s", ncmpi_strerror(err));
-    {
-	int dimids[NDIMS +1];
-	int ii = 0;
-	for(ii = 0; ii < NDIMS; ii++)
-		dimids[ii] = ii;
-	dimids[NDIMS] = dimid;
-    	err = ncmpi_def_var(ncid, "abcRec", NC_INT, NDIMS, dimids, &varid1);
-    	IF (err != NC_NOERR)
-        	error("ncmpi_def_var: %s", ncmpi_strerror(err));
-    }
-    err = ncmpi_put_att_text(ncid, NC_GLOBAL, "title", 1+strlen(title), title);
-    IF (err != NC_NOERR)
-        error("ncmpi_put_att_text: %s", ncmpi_strerror(err));
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    var = 1.0;
-    err = ncmpi_end_indep_data(ncid);
-    IF (err != NC_ENOTINDEP)
-        error("ncmpi_end_indep_data: in collective mode status = %s", ncmpi_strerror(err));
-    err = ncmpi_begin_indep_data(ncid);
-    IF (err != NC_NOERR) 
-	error("ncmpi_begin_indep_data: %s", ncmpi_strerror(err));
-    err = ncmpi_put_var1_double(ncid, varid, NULL, &var);
-    IF (err != NC_NOERR)
-        error("ncmpi_put_var1_double: %s", ncmpi_strerror(err));
-    err = ncmpi_end_indep_data(ncid);
-    IF (err != NC_NOERR) 
-	error("ncmpi_begin_indep_data: %s", ncmpi_strerror(err));
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR) 
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-
-	/* check scratch file written as expected */
-    check_file(scratch);
-    err = ncmpi_open(comm, scratch, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_inq_dim(ncid, dimid, name, &length);
-    IF (err != NC_NOERR) 
-	error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
-    IF (strcmp(name, "abc") != 0) 
-	error("Unexpected dim name");
-    IF (length != sizehint) 
-	error("Unexpected dim length");
-    ncmpi_begin_indep_data(ncid);
-    err = ncmpi_get_var1_double(ncid, varid, NULL, &var);
-    IF (err != NC_NOERR)
-        error("ncmpi_get_var1_double: %s", ncmpi_strerror(err));
-    ncmpi_end_indep_data(ncid);
-    IF (var != 1.0)
-        error("ncmpi_get_var1_double: unexpected value");
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_enddef 
- * Simply calls test_ncmpi_redef which tests both ncmpi_redef & ncmpi_enddef
- */
-int
-test_ncmpi_enddef(void)
-{
-    return test_ncmpi_redef();
-}
-
-
-/*
- * Test ncmpi_sync
- *    try with bad handle, check error
- *    try in define mode, check error
- *    try writing with one handle, reading with another on same netCDF
- */
-int
-test_ncmpi_sync(void)
-{
-    int ncidw;         /* netcdf id for writing */
-    int ncidr;         /* netcdf id for reading */
-    int nok=0, err;
-
-    /* BAD_ID test */
-    err = ncmpi_sync(BAD_ID);
-    IF (err != NC_EBADID)
-        error("bad ncid: status = %d", err);
-    ELSE_NOK
-
-        /* create scratch file & try ncmpi_sync in define mode */
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncidw);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-	return nok;
-    }
-    err = ncmpi_sync(ncidw);
-    IF (err != NC_EINDEFINE)
-        error("ncmpi_sync called in define mode: status = %d", err);
-    ELSE_NOK
-
-    /* write using same handle */
-    def_dims(ncidw);
-    def_vars(ncidw);
-    put_atts(ncidw);
-    err = ncmpi_enddef(ncidw);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    put_vars(ncidw);
-    err = ncmpi_sync(ncidw);
-    IF (err != NC_NOERR)
-        error("ncmpi_sync of ncidw failed: %s", ncmpi_strerror(err));
-    ELSE_NOK
-
-    /* open another handle, ncmpi_sync, read (check) */
-    err = ncmpi_open(comm, scratch, NC_NOWRITE, info, &ncidr);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_sync(ncidr);
-    IF (err != NC_NOERR)
-        error("ncmpi_sync of ncidr failed: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    check_dims(ncidr);
-    check_atts(ncidr);
-    check_vars(ncidr);
-
-    /* close both handles */
-    err = ncmpi_close(ncidr);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_close(ncidw);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_abort
- *    try with bad handle, check error
- *    try in define mode before anything written, check that file was deleted
- *    try after ncmpi_enddef, ncmpi_redef, define new dims, vars, atts
- *    try after writing variable
- */
-int
-test_ncmpi_abort(void)
-{
-    int ncid;          /* netcdf id */
-    int err;
-    int ndims;
-    int nvars;
-    int ngatts;
-    int nok=0;
-
-    /* BAD_ID test */
-    err = ncmpi_abort(BAD_ID);
-    IF (err != NC_EBADID)
-        error("bad ncid: status = %d", err);
-    ELSE_NOK
-
-        /* create scratch file & try ncmpi_abort in define mode */
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid);
-    def_vars(ncid);
-    put_atts(ncid);
-    err = ncmpi_abort(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_abort of ncid failed: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    err = ncmpi_close(ncid);	/* should already be closed */
-    IF (err != NC_EBADID)
-        error("bad ncid: status = %d", err);
-    err = ncmpi_delete(scratch, info);	/* should already be deleted */
-    IF (!err) /* err is expected to be NC_ENOENT */
-        error("file %s should not exist", scratch);
-
-        /* 
-         * create scratch file
-	 * do ncmpi_enddef & ncmpi_redef
-	 * define new dims, vars, atts
-	 * try ncmpi_abort: should restore previous state (no dims, vars, atts)
-	 */ 
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    err = ncmpi_redef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_redef: %s", ncmpi_strerror(err));
-    def_dims(ncid);
-    def_vars(ncid);
-    put_atts(ncid);
-    err = ncmpi_abort(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_abort of ncid failed: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    err = ncmpi_close(ncid);	/* should already be closed */
-    IF (err != NC_EBADID)
-        error("bad ncid: status = %d", err);
-    err = ncmpi_open(comm, scratch, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_inq (ncid, &ndims, &nvars, &ngatts, NULL);
-    IF (err != NC_NOERR)
-        error("ncmpi_inq: %s", ncmpi_strerror(err));
-    IF (ndims != 0)
-        error("ndims should be 0");
-    IF (nvars != 0)
-        error("nvars should be 0");
-    IF (ngatts != 0)
-        error("ngatts should be 0");
-    err = ncmpi_close (ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    /* try ncmpi_abort in data mode - should just close */
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid);
-    def_vars(ncid);
-    put_atts(ncid);
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    put_vars(ncid);
-    err = ncmpi_abort(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_abort of ncid failed: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    err = ncmpi_close(ncid);       /* should already be closed */
-    IF (err != NC_EBADID)
-        error("bad ncid: status = %d", err);
-    check_file(scratch);
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_def_dim
- *    try with bad netCDF handle, check error
- *    try in data mode, check error
- *    check that returned id is one more than previous id
- *    try adding same dimension twice, check error
- *    try with illegal sizes, check error
- *    make sure unlimited size works, shows up in ncmpi_inq_unlimdim
- *    try to define a second unlimited dimension, check error
- */
-int
-test_ncmpi_def_dim(void)
-{
-    int ncid;
-    int  err;             /* status */
-    int  i, nok=0;
-    int  dimid;         /* dimension id */
-    MPI_Offset length;
-
-        /* BAD_ID test */
-    err = ncmpi_def_dim(BAD_ID, "abc", 8, &dimid);
-    IF (err != NC_EBADID)
-        error("bad ncid: status = %d", err);
-    ELSE_NOK
-
-        /* data mode test */
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    err = ncmpi_def_dim(ncid, "abc", 8, &dimid);
-    IF (err != NC_ENOTINDEFINE)
-        error("bad ncid: status = %d", err);
-    ELSE_NOK
-
-    /* define-mode tests: unlimited dim */
-    err = ncmpi_redef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_redef: %s", ncmpi_strerror(err));
-    err = ncmpi_def_dim(ncid, dim_name[0], NC_UNLIMITED, &dimid);
-    IF (err != NC_NOERR) 
-	error("ncmpi_def_dim: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    IF (dimid != 0) 
-	error("Unexpected dimid");
-    ELSE_NOK
-    err = ncmpi_inq_unlimdim(ncid, &dimid);
-    IF (err != NC_NOERR) 
-	error("ncmpi_inq_unlimdim: %s", ncmpi_strerror(err));
-    IF (dimid != 0) 
-	error("Unexpected recdim");
-    err = ncmpi_inq_dimlen(ncid, dimid, &length);
-    IF (length != 0) 
-	error("Unexpected length");
-    err = ncmpi_def_dim(ncid, "abc", NC_UNLIMITED, &dimid);
-    IF (err != NC_EUNLIMIT)
-        error("2nd unlimited dimension: status = %d", err);
-    ELSE_NOK
-
-    /* define-mode tests: remaining dims */
-    for (i = 1; i < NDIMS; i++) {
-        err = ncmpi_def_dim(ncid, dim_name[i-1], dim_len[i], &dimid);
-	IF (err != NC_ENAMEINUSE)
-	    error("duplicate name: status = %d", err);
-        ELSE_NOK
-	err = ncmpi_def_dim(ncid, BAD_NAME, dim_len[i], &dimid);
-	IF (err != NC_EBADNAME)
-	    error("bad name: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_def_dim(ncid, dim_name[i], NC_UNLIMITED-1, &dimid);
-	IF (err != NC_EDIMSIZE)
-	    error("bad size: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_def_dim(ncid, dim_name[i], dim_len[i], &dimid);
-        IF (err != NC_NOERR) 
-	    error("ncmpi_def_dim: %s", ncmpi_strerror(err));
-        ELSE_NOK
-	IF (dimid != i) 
-	    error("Unexpected dimid");
-    }
-
-        /* Following just to expand unlimited dim */
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    put_vars(ncid);
-
-        /* Check all dims */
-    check_dims(ncid);
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_rename_dim
- *    try with bad netCDF handle, check error
- *    check that proper rename worked with ncmpi_inq_dim
- *    try renaming to existing dimension name, check error
- *    try with bad dimension handle, check error
- */
-int
-test_ncmpi_rename_dim(void)
-{
-    int ncid;
-    int  err, nok=0;             /* status */
-    char name[NC_MAX_NAME];
-
-        /* BAD_ID test */
-    err = ncmpi_rename_dim(BAD_ID, 0, "abc");
-    IF (err != NC_EBADID)
-        error("bad ncid: status = %d", err);
-    ELSE_NOK
-
-        /* main tests */
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid);
-    err = ncmpi_rename_dim(ncid, BAD_DIMID, "abc");
-    IF (err != NC_EBADDIM)
-        error("bad dimid: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_rename_dim(ncid, 2, "abc");
-    IF (err != NC_NOERR)
-        error("ncmpi_rename_dim: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    err = ncmpi_inq_dimname(ncid, 2, name);
-    IF (strcmp(name, "abc") != 0)
-        error("Unexpected name: %s", name);
-    err = ncmpi_rename_dim(ncid, 0, "abc");
-    IF (err != NC_ENAMEINUSE)
-        error("duplicate name: status = %d", err);
-    ELSE_NOK
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_def_var
- *    try with bad netCDF handle, check error
- *    try with bad name, check error
- *    scalar tests:
- *      check that proper define worked with ncmpi_inq_var
- *      try redefining an existing variable, check error
- *      try with bad datatype, check error
- *      try with bad number of dimensions, check error
- *      try in data mode, check error
- *    check that returned id is one more than previous id
- *    try with bad dimension ids, check error
- */
-int
-test_ncmpi_def_var(void)
-{
-    int  ncid;
-    int  varid;
-    int  err, nok=0;             /* status */
-    int  i;
-    int  ndims;
-    int  natts;
-    char name[NC_MAX_NAME];
-    int dimids[MAX_RANK];
-    nc_type datatype;
-
-        /* BAD_ID test */
-    err = ncmpi_def_var(BAD_ID, "abc", NC_SHORT, 0, NULL, &varid);
-    IF (err != NC_EBADID)
-        error("bad ncid: status = %d", err);
-    ELSE_NOK
-
-        /* scalar tests */
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    err = ncmpi_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid);
-    IF (err != NC_NOERR)
-        error("ncmpi_def_var: %s", ncmpi_strerror(err));
-    ELSE_NOK
-    err = ncmpi_inq_var(ncid, varid, name, &datatype, &ndims, dimids, &natts);
-    IF (err != NC_NOERR)
-        error("ncmpi_inq_var: %s", ncmpi_strerror(err));
-    IF (strcmp(name, "abc") != 0)
-        error("Unexpected name: %s", name);
-    IF (datatype != NC_SHORT)
-        error("Unexpected datatype");
-    IF (ndims != 0)
-        error("Unexpected rank");
-    err = ncmpi_def_var(ncid, BAD_NAME, NC_SHORT, 0, NULL, &varid);
-    IF (err != NC_EBADNAME)
-        error("bad name: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid);
-    IF (err != NC_ENAMEINUSE)
-        error("duplicate name: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_def_var(ncid, "ABC", BAD_TYPE, -1, dimids, &varid);
-    IF (err != NC_EBADTYPE)
-        error("bad type: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_def_var(ncid, "ABC", NC_SHORT, -1, dimids, &varid);
-    IF (err != NC_EINVAL)
-        error("bad rank: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-	error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    err = ncmpi_def_var(ncid, "ABC", NC_SHORT, 0, dimids, &varid);
-    IF (err != NC_ENOTINDEFINE)
-        error("ncmpi_def_var called in data mode: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-
-    /* general tests using global vars */
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid);
-    for (i = 0; i < numVars; i++) {
-        err = ncmpi_def_var(ncid, var_name[i], var_type[i], var_rank[i],
-            var_dimid[i], &varid);
-        IF (err != NC_NOERR) 
-	    error("ncmpi_def_var: %s", ncmpi_strerror(err));
-        ELSE_NOK
-	IF (varid != i)
-	    error("Unexpected varid");
-        ELSE_NOK
-    }
-
-    /* try bad dim ids */
-    dimids[0] = BAD_DIMID;
-    err = ncmpi_def_var(ncid, "abc", NC_SHORT, 1, dimids, &varid);
-    IF (err != NC_EBADDIM)
-        error("bad dim ids: status = %d", err);
-    ELSE_NOK
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_put_var1
- */
-int
-test_ncmpi_put_var1(void)
-{
-    int i, j, err, ncid, nok=0;
-    MPI_Offset index[MAX_RANK];
-    MPI_Datatype buftype;
-    double value;
-    double buf[1];		/* (void *) buffer */
-
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-
-    /* var1 is only available for indep mode */
-    err = ncmpi_begin_indep_data(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_begin_indep_data: %s", ncmpi_strerror(err));
-
-    for (i = 0; i < numVars; i++) {
-        buftype = nc_mpi_type(var_type[i]);
-        for (j = 0; j < var_rank[i]; j++)
-            index[j] = 0;
-        err = ncmpi_put_var1(BAD_ID, i, index, buf, 1, buftype);
-        IF (err != NC_EBADID)
-            error("bad ncid: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_put_var1(ncid, BAD_VARID, index, buf, 1, buftype);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: status = %d", err);
-        ELSE_NOK
-        for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {          /* skip record dim */
-                index[j] = var_shape[i][j];
-                err = ncmpi_put_var1(ncid, i, index, buf, 1, buftype);
-                IF (err != NC_EINVALCOORDS)
-                    error("bad index: status = %d", err);
-                ELSE_NOK
-                index[j] = 0;
-            }
-        }
-        for (j = 0; j < var_nels[i]; j++) {
-            err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR)
-                error("error in toMixedBase");
-            value = hash(var_type[i], var_rank[i], index);
-	    if (inRange(value, var_type[i])) {
-		err = dbl2nc(value, var_type[i], buf);
-		IF (err != NC_NOERR)
-		    error("error in dbl2nc");
-		if (var_rank[i] == 0 && i%2 == 0)
-		    err = ncmpi_put_var1(ncid, i, NULL, buf, 1, buftype);
-		else
-		    err = ncmpi_put_var1(ncid, i, index, buf, 1, buftype);
-		IF (err != NC_NOERR)
-		    error("%s", ncmpi_strerror(err));
-                ELSE_NOK
-	    }
-        }
-    }
-    err = ncmpi_end_indep_data(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_end_indep_data: %s", ncmpi_strerror(err));
-
-    check_vars(ncid);
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_put_vara
- * Choose a random point dividing each dim into 2 parts
- * Put 2^rank (nslabs) slabs so defined
- * Redefine buffer for each put.
- * At end check all variables using check_vars
- */
-int
-test_ncmpi_put_vara(void)
-{
-    int d, i, j, k, err, nels,nslabs, ncid, nok=0;
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset bufcount;
-    MPI_Datatype buftype;
-    double buf[MAX_NELS]; 	/* (void *) buffer */
-    char *p;			/* (void *) pointer */
-    double value;
-
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-
-    for (i = 0; i < numVars; i++) {
-        assert(var_rank[i] <= MAX_RANK);
-        assert(var_nels[i] <= MAX_NELS);
-        for (j = 0; j < var_rank[i]; j++) {
-            start[j] = 0;
-            edge[j] = 1;
-        }
-        buftype = nc_mpi_type(var_type[i]);
-        for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= edge[j];
-        err = ncmpi_put_vara_all(BAD_ID, i, start, edge, buf, bufcount, buftype);
-        IF (err != NC_EBADID)
-            error("expecting bad ncid: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_put_vara_all(ncid, BAD_VARID, start, edge, buf, bufcount, buftype);
-        IF (err != NC_ENOTVAR)
-            error("expecting bad var id: status = %d", err);
-        ELSE_NOK
-        for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {          /* skip record dim */
-		start[j] = var_shape[i][j];
-                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
-		err = ncmpi_put_vara_all(ncid, i, start, edge, buf, bufcount, buftype);
-                IF (err != NC_EINVALCOORDS)
-                    error("expecting bad start, but err = %d", err);
-                ELSE_NOK
-		start[j] = 0;
-		edge[j] = var_shape[i][j] + 1;
-                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
-		err = ncmpi_put_vara_all(ncid, i, start, edge, buf, bufcount, buftype);
-                IF (err != NC_EEDGE)
-                    error("expecting bad edge, but err = %d", err);
-                ELSE_NOK
-		edge[j] = 1;
-	    }
-        }
-            /* Choose a random point dividing each dim into 2 parts */
-            /* put 2^rank (nslabs) slabs so defined */
-        nslabs = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            mid[j] = roll( var_shape[i][j] );
-            nslabs *= 2;
-        }
-            /* bits of k determine whether to put lower or upper part of dim */
-        for (k = 0; k < nslabs; k++) {
-            nels = 1;
-            for (j = 0; j < var_rank[i]; j++) {
-                if ((k >> j) & 1) {
-                    start[j] = 0;
-                    edge[j] = mid[j];
-                }else{
-                    start[j] = mid[j];
-                    edge[j] = var_shape[i][j] - mid[j];
-                }
-                nels *= edge[j];
-            }
-	    p = (char *) buf;
-	    for (j = 0; j < nels; j++) {
-		err = toMixedBase(j, var_rank[i], edge, index);
-		IF (err != NC_NOERR)
-		    error("error in toMixedBase");
-		for (d = 0; d < var_rank[i]; d++)
-		    index[d] += start[d];
-		value = hash(var_type[i], var_rank[i], index);
-		if (!inRange(value, var_type[i]))
-		    value = 0;
-		err = dbl2nc(value, var_type[i], p);
-		IF (err != NC_NOERR)
-		    error("error in dbl2nc");
-		p += nctypelen(var_type[i]);
-            }
-            for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= edge[j];
-            if (var_rank[i] == 0 && i%2 == 0)
-		err = ncmpi_put_vara_all(ncid, i, NULL, NULL, buf, bufcount, buftype);
-            else
-		err = ncmpi_put_vara_all(ncid, i, start, edge, buf, bufcount, buftype);
-            IF (err != NC_NOERR)
-                error("%s", ncmpi_strerror(err));
-            ELSE_NOK
-        }
-    }
-
-    check_vars(ncid);
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_put_vars
- * Choose a random point dividing each dim into 2 parts
- * Put 2^rank (nslabs) slabs so defined
- * Choose random stride from 1 to edge
- * Redefine buffer for each put.
- * At end check all variables using check_vars
- */
-int
-test_ncmpi_put_vars(void)
-{
-    int ncid, d, i, j, k, m, err, nels, nslabs, nok=0;
-    int nstarts;        /* number of different starts */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset index2[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    MPI_Offset bufcount;
-    MPI_Datatype buftype;
-    double buf[MAX_NELS]; /* (void *) buffer */
-    char *p;			/* (void *) pointer */
-    double value;
-
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-
-    for (i = 0; i < numVars; i++) {
-        assert(var_rank[i] <= MAX_RANK);
-        assert(var_nels[i] <= MAX_NELS);
-        for (j = 0; j < var_rank[i]; j++) {
-            start[j] = 0;
-            edge[j] = 1;
-            stride[j] = 1;
-        }
-        buftype = nc_mpi_type(var_type[i]);
-        for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= edge[j];
-        err = ncmpi_put_vars_all(BAD_ID, i, start, edge, stride, buf, bufcount, buftype);
-        IF (err != NC_EBADID)
-            error("bad ncid: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_put_vars_all(ncid, BAD_VARID, start, edge, stride, buf, bufcount, buftype);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: status = %d", err);
-        ELSE_NOK
-        for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {          /* skip record dim */
-		start[j] = var_shape[i][j];
-                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
-		err = ncmpi_put_vars_all(ncid, i, start, edge, stride, buf, bufcount, buftype);
-		IF (err != NC_EINVALCOORDS)
-		    error("bad index: status = %d", err);
-                ELSE_NOK
-		start[j] = 0;
-		edge[j] = var_shape[i][j] + 1;
-                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
-		err = ncmpi_put_vars_all(ncid, i, start, edge, stride, buf, bufcount, buftype);
-		IF (err != NC_EEDGE)
-		    error("bad edge: status = %d", err);
-                ELSE_NOK
-		edge[j] = 1;
-		stride[j] = 0;
-                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
-		err = ncmpi_put_vars_all(ncid, i, start, edge, stride, buf, bufcount, buftype);
-		IF (err != NC_ESTRIDE)
-		    error("bad stride: status = %d", err);
-                ELSE_NOK
-		stride[j] = 1;
-	    }
-        }
-            /* Choose a random point dividing each dim into 2 parts */
-            /* put 2^rank (nslabs) slabs so defined */
-        nslabs = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            mid[j] = roll( var_shape[i][j] );
-            nslabs *= 2;
-        }
-            /* bits of k determine whether to put lower or upper part of dim */
-            /* choose random stride from 1 to edge */
-        for (k = 0; k < nslabs; k++) {
-            nstarts = 1;
-            for (j = 0; j < var_rank[i]; j++) {
-                if ((k >> j) & 1) {
-                    start[j] = 0;
-                    edge[j] = mid[j];
-                }else{
-                    start[j] = mid[j];
-                    edge[j] = var_shape[i][j] - mid[j];
-                }
-                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
-                nstarts *= stride[j];
-            }
-            for (m = 0; m < nstarts; m++) {
-                err = toMixedBase(m, var_rank[i], sstride, index);
-                IF (err != NC_NOERR)
-                    error("error in toMixedBase");
-                nels = 1;
-                for (j = 0; j < var_rank[i]; j++) {
-                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
-                    nels *= count[j];
-                    index[j] += start[j];
-                }
-                        /* Random choice of forward or backward */
-/* TODO
-                if ( roll(2) ) {
-                    for (j = 0; j < var_rank[i]; j++) {
-                        index[j] += (count[j] - 1) * stride[j];
-                        stride[j] = -stride[j];
-                    }
-                }
- */
-		p = (char *) buf;
-		for (j = 0; j < nels; j++) {
-		    err = toMixedBase(j, var_rank[i], count, index2);
-		    IF (err != NC_NOERR)
-			error("error in toMixedBase");
-		    for (d = 0; d < var_rank[i]; d++)
-			index2[d] = index[d] + index2[d] * stride[d];
-		    value = hash(var_type[i], var_rank[i], index2);
-		    if (!inRange(value, var_type[i]))
-			value = 0;
-		    err = dbl2nc(value, var_type[i], p);
-		    IF (err != NC_NOERR)
-			error("error in dbl2nc");
-		    p += nctypelen(var_type[i]);
-		}
-                for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= count[j];
-		if (var_rank[i] == 0 && i%2 == 0)
-		    err = ncmpi_put_vars_all(ncid, i, NULL, NULL, NULL, buf, bufcount, buftype);
-		else
-		    err = ncmpi_put_vars_all(ncid, i, index, count, stride, buf, bufcount, buftype);
-		IF (err != NC_NOERR)
-		    error("%s", ncmpi_strerror(err));
-                ELSE_NOK
-            }
-        }
-    }
-
-    check_vars(ncid);
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_put_varm
- * Choose a random point dividing each dim into 2 parts
- * Put 2^rank (nslabs) slabs so defined
- * Choose random stride from 1 to edge
- * Buffer is bit image of whole external variable.
- * So all puts for a variable put different elements of buffer
- * At end check all variables using check_vars
- */
-int
-test_ncmpi_put_varm(void)
-{
-    int ncid, nok=0;
-    int i;
-    int j;
-    int k;
-    int m;
-    int err;
-    int nslabs;
-    int nstarts;        /* number of different starts */
-    MPI_Offset start[MAX_RANK];
-    MPI_Offset edge[MAX_RANK];
-    MPI_Offset index[MAX_RANK];
-    MPI_Offset mid[MAX_RANK];
-    MPI_Offset count[MAX_RANK];
-    MPI_Offset sstride[MAX_RANK];
-    MPI_Offset stride[MAX_RANK];
-    MPI_Offset imap[MAX_RANK];
-    MPI_Offset imap2[MAX_RANK];
-    MPI_Offset bufcount;
-    MPI_Datatype buftype;
-    double buf[MAX_NELS];       /* (void *) buffer */
-    char *p;			/* (void *) pointer */
-    double value;
-
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid);
-    def_vars(ncid);
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-
-    for (i = 0; i < numVars; i++) {
-        assert(var_rank[i] <= MAX_RANK);
-        assert(var_nels[i] <= MAX_NELS);
-        for (j = 0; j < var_rank[i]; j++) {
-            start[j] = 0;
-            edge[j] = 1;
-            stride[j] = 1;
-        }
-	if (var_rank[i] > 0) {
-	    j = var_rank[i] - 1; 
-	    imap[j] = nctypelen(var_type[i]); /*  netCDF considers imap in bytes */
-	    imap[j] = 1;                      /* PnetCDF considers imap in elements */
-	    for (; j > 0; j--)
-		imap[j-1] = imap[j] * var_shape[i][j];
-	}
-	p = (char *) buf;
-	for (j = 0; j < var_nels[i]; j++) {
-	    err = toMixedBase(j, var_rank[i], var_shape[i], index);
-	    IF (err != NC_NOERR)
-		error("error in toMixedBase");
-	    value = hash(var_type[i], var_rank[i], index);
-	    if (!inRange(value, var_type[i]))
-		value = 0;
-	    err = dbl2nc(value, var_type[i], p);
-	    IF (err != NC_NOERR)
-		error("error in dbl2nc");
-	    p += nctypelen(var_type[i]);
-	}
-        buftype = nc_mpi_type(var_type[i]);
-        for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= edge[j];
-        err = ncmpi_put_varm_all(BAD_ID, i, start, edge, stride, imap, buf, bufcount, buftype);
-        IF (err != NC_EBADID)
-            error("bad ncid: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_put_varm_all(ncid, BAD_VARID, start, edge, stride, imap, buf, bufcount, buftype);
-        IF (err != NC_ENOTVAR)
-            error("bad var id: status = %d", err);
-        ELSE_NOK
-        for (j = 0; j < var_rank[i]; j++) {
-            if (var_dimid[i][j] > 0) {          /* skip record dim */
-		start[j] = var_shape[i][j];
-                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
-		err = ncmpi_put_varm_all(ncid, i, start, edge, stride, imap, buf, bufcount, buftype);
-		IF (err != NC_EINVALCOORDS)
-		    error("bad index: status = %d", err);
-                ELSE_NOK
-		start[j] = 0;
-		edge[j] = var_shape[i][j] + 1;
-                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
-		err = ncmpi_put_varm_all(ncid, i, start, edge, stride, imap, buf, bufcount, buftype);
-		IF (err != NC_EEDGE)
-		    error("bad edge: status = %d", err);
-                ELSE_NOK
-		edge[j] = 1;
-		stride[j] = 0;
-                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
-		err = ncmpi_put_varm_all(ncid, i, start, edge, stride, imap, buf, bufcount, buftype);
-		IF (err != NC_ESTRIDE)
-		    error("bad stride: status = %d", err);
-                ELSE_NOK
-		stride[j] = 1;
-	    }
-        }
-            /* Choose a random point dividing each dim into 2 parts */
-            /* put 2^rank (nslabs) slabs so defined */
-        nslabs = 1;
-        for (j = 0; j < var_rank[i]; j++) {
-            mid[j] = roll( var_shape[i][j] );
-            nslabs *= 2;
-        }
-            /* bits of k determine whether to put lower or upper part of dim */
-            /* choose random stride from 1 to edge */
-        for (k = 0; k < nslabs; k++) {
-            nstarts = 1;
-            for (j = 0; j < var_rank[i]; j++) {
-                if ((k >> j) & 1) {
-                    start[j] = 0;
-                    edge[j] = mid[j];
-                }else{
-                    start[j] = mid[j];
-                    edge[j] = var_shape[i][j] - mid[j];
-                }
-                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
-                imap2[j] = imap[j] * sstride[j];
-                nstarts *= stride[j];
-            }
-            for (m = 0; m < nstarts; m++) {
-		if (var_rank[i] == 0 && i%2 == 0) {
-		    err = ncmpi_put_varm_all(ncid, i, NULL, NULL, NULL, NULL, buf, 1, buftype);
-		} else {
-		    err = toMixedBase(m, var_rank[i], sstride, index);
-		    IF (err != NC_NOERR)
-			error("error in toMixedBase");
-		    for (j = 0; j < var_rank[i]; j++) {
-			count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
-			index[j] += start[j];
-		    }
-			    /* Random choice of forward or backward */
-/* TODO
-		    if ( roll(2) ) {
-			for (j = 0; j < var_rank[i]; j++) {
-			    index[j] += (count[j] - 1) * stride[j];
-			    stride[j] = -stride[j];
-			}
-		    }
- */
-		    j = fromMixedBase(var_rank[i], index, var_shape[i]);
-                    p = (char *) buf + j * nctypelen(var_type[i]);
-                    for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= count[j];
-		    err = ncmpi_put_varm_all(ncid, i, index, count, stride, imap2, p, bufcount, buftype);
-		}
-		IF (err != NC_NOERR)
-		    error("i=%d var_rank[i]=%d %s", i,var_rank[i],ncmpi_strerror(err));
-                ELSE_NOK
-            }
-        }
-    }
-
-    check_vars(ncid);
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_rename_var
- *    try with bad netCDF handle, check error
- *    try with bad variable handle, check error
- *    try renaming to existing variable name, check error
- *    check that proper rename worked with ncmpi_inq_varid
- *    try in data mode, check error
- */
-int
-test_ncmpi_rename_var(void)
-{
-    int ncid;
-    int varid;
-    int err, nok=0;
-    int i;
-    char name[NC_MAX_NAME];
-
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    err = ncmpi_rename_var(ncid, BAD_VARID, "newName");
-    IF (err != NC_ENOTVAR)
-	error("bad var id: status = %d", err);
-    ELSE_NOK
-    def_dims(ncid);
-    def_vars(ncid);
-
-	/* Prefix "new_" to each name */
-    for (i = 0; i < numVars; i++) {
-        err = ncmpi_rename_var(BAD_ID, i, "newName");
-        IF (err != NC_EBADID)
-            error("bad ncid: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_rename_var(ncid, i, var_name[numVars-1]);
-        IF (err != NC_ENAMEINUSE)
-            error("duplicate name: status = %d", err);
-        ELSE_NOK
-	strcpy(name, "new_");
-	strcat(name, var_name[i]);
-        err = ncmpi_rename_var(ncid, i, name);
-        IF (err != NC_NOERR)
-	    error("ncmpi_rename_var: %s", ncmpi_strerror(err));
-        ELSE_NOK
-        err = ncmpi_inq_varid(ncid, name, &varid);
-        IF (err != NC_NOERR)
-	    error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
-        IF (varid != i)
-	    error("Unexpected varid");
-    }
-
-	/* Change to data mode */
-	/* Try making names even longer. Then restore original names */
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    for (i = 0; i < numVars; i++) {
-	strcpy(name, "even_longer_");
-	strcat(name, var_name[i]);
-        err = ncmpi_rename_var(ncid, i, name);
-        IF (err != NC_ENOTINDEFINE)
-            error("longer name in data mode: status = %d", err);
-        ELSE_NOK
-        err = ncmpi_rename_var(ncid, i, var_name[i]);
-        IF (err != NC_NOERR)
-	    error("ncmpi_rename_var: %s", ncmpi_strerror(err));
-        ELSE_NOK
-        err = ncmpi_inq_varid(ncid, var_name[i], &varid);
-        IF (err != NC_NOERR)
-	    error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
-        IF (varid != i)
-	    error("Unexpected varid");
-    }
-
-    put_vars(ncid);
-    check_vars(ncid);
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-int
-test_ncmpi_put_att(void)
-{
-    int ncid, nok=0;
-    int varid;
-    int i;
-    int j;
-    MPI_Offset k;
-    int err;
-    double buf[MAX_NELS];       /* (void *) buffer */
-    char *p;                    /* (void *) pointer */
-    char *name;			/* of att */
-    nc_type datatype;		/* of att */
-    MPI_Offset length;		/* of att */
-    double value;
-
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid);
-    def_vars(ncid);
-
-    for (i = -1; i < numVars; i++) {
-	varid = VARID(i);
-        for (j = 0; j < NATTS(i); j++) {
-	    name = ATT_NAME(i,j);
-	    datatype = ATT_TYPE(i,j);
-	    length = ATT_LEN(i,j);
-            err = ncmpi_put_att(BAD_ID, varid, name, datatype, length, buf);
-            IF (err != NC_EBADID)
-                error("bad ncid: status = %d", err);
-            ELSE_NOK
-            err = ncmpi_put_att(ncid, varid, BAD_NAME, datatype, length, buf);
-	    IF (err != NC_EBADNAME)
-		error("bad name: status = %d", err);
-            ELSE_NOK
-            err = ncmpi_put_att(ncid, BAD_VARID, name, datatype, length, buf);
-            IF (err != NC_ENOTVAR)
-                error("bad var id: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_put_att(ncid, varid, name, BAD_TYPE, length, buf);
-	    IF (err != NC_EBADTYPE)
-		error("bad type: status = %d", err);
-            ELSE_NOK
-	    p = (char *) buf;
-	    for (k=0; k<length; k++) {
-		value = hash(datatype, -1, &k);
-		if (!inRange(value, datatype))
-		    value = 0;
-		err = dbl2nc(value, datatype, p);
-		IF (err != NC_NOERR)
-		    error("error in dbl2nc");
-		p += nctypelen(datatype);
-	    }
-            err = ncmpi_put_att(ncid, varid, name, datatype, length, buf);
-            IF (err != NC_NOERR)
-                error("%s", ncmpi_strerror(err));
-            ELSE_NOK
-        }
-    }
-
-    check_atts(ncid);
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_copy_att
- *    try with bad source or target netCDF handles, check error
- *    try with bad source or target variable handle, check error
- *    try with nonexisting attribute, check error
- *    check that NC_GLOBAL variable for source or target works
- *    check that new attribute put works with target in define mode
- *    check that old attribute put works with target in data mode
- *    check that changing type and length of an attribute work OK
- *    try with same ncid for source and target, different variables
- *    try with same ncid for source and target, same variable
- */
-int
-test_ncmpi_copy_att(void)
-{
-    int ncid_in;
-    int ncid_out;
-    int varid;
-    int err, nok=0;
-    int i;
-    int j=0;
-    char *name;                 /* of att */
-    nc_type datatype;           /* of att */
-    MPI_Offset length;          /* of att */
-    char  value;
-
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid_in);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid_out);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid_out);
-    def_vars(ncid_out);
-
-    for (i = -1; i < numVars; i++) {
-        varid = VARID(i);
-        for (j = 0; j < NATTS(i); j++) {
-            name = ATT_NAME(i,j);
-	    err = ncmpi_copy_att(ncid_in, BAD_VARID, name, ncid_out, varid);
-	    IF (err != NC_ENOTVAR)
-		error("bad var id: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_copy_att(ncid_in, varid, name, ncid_out, BAD_VARID);
-	    IF (err != NC_ENOTVAR)
-		error("bad var id: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_copy_att(BAD_ID, varid, name, ncid_out, varid);
-	    IF (err != NC_EBADID)
-		error("bad ncid: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_copy_att(ncid_in, varid, name, BAD_ID, varid);
-	    IF (err != NC_EBADID)
-		error("bad ncid: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_copy_att(ncid_in, varid, "noSuch", ncid_out, varid);
-	    IF (err != NC_ENOTATT)
-		error("bad attname: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_copy_att(ncid_in, varid, name, ncid_out, varid);
-	    IF (err != NC_NOERR)
-		error("ncmpi_copy_att: %s", ncmpi_strerror(err));
-            ELSE_NOK
-	    err = ncmpi_copy_att(ncid_out, varid, name, ncid_out, varid);
-	    IF (err != NC_NOERR)
-		error("source = target: %s", ncmpi_strerror(err));
-            ELSE_NOK
-	}
-    }
-
-    err = ncmpi_close(ncid_in);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-        /* Close scratch. Reopen & check attributes */
-    err = ncmpi_close(ncid_out);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_open(comm, scratch, NC_WRITE, info, &ncid_out);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-    check_atts(ncid_out);
-
-       /* 
-	* change to define mode
-	* define single char. global att. ':a' with value 'A'
-	* This will be used as source for following copies
-	*/
-    err = ncmpi_redef(ncid_out);
-    IF (err != NC_NOERR)
-        error("ncmpi_redef: %s", ncmpi_strerror(err));
-    err = ncmpi_put_att_text(ncid_out, NC_GLOBAL, "a", 1, "A");
-    IF (err != NC_NOERR)
-	error("ncmpi_put_att_text: %s", ncmpi_strerror(err));
-
-       /* 
-	* change to data mode
-	* Use scratch as both source & dest.
-	* try copy to existing att. change type & decrease length
-	* rename 1st existing att of each var (if any) 'a'
-	* if this att. exists them copy ':a' to it
-	*/
-    err = ncmpi_enddef(ncid_out);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    for (i = 0; i < numVars; i++) {
-	if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
-	    err = ncmpi_rename_att(ncid_out, i, att_name[i][0], "a");
-	    IF (err != NC_NOERR)
-		error("ncmpi_rename_att: %s", ncmpi_strerror(err));
-	    err = ncmpi_copy_att(ncid_out, NC_GLOBAL, "a", ncid_out, i);
-	    IF (err != NC_NOERR)
-		error("ncmpi_copy_att: %s", ncmpi_strerror(err));
-            ELSE_NOK
-	}
-    }
-    err = ncmpi_close(ncid_out);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-	/* Reopen & check */
-    err = ncmpi_open(comm, scratch, NC_WRITE, info, &ncid_out);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-    for (i = 0; i < numVars; i++) {
-	if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
-	    err = ncmpi_inq_att(ncid_out, i, "a", &datatype, &length);
-	    IF (err != NC_NOERR)
-		error("ncmpi_inq_att: %s", ncmpi_strerror(err));
-	    IF (datatype != NC_CHAR)
-		error("Unexpected type");
-	    IF (length != 1)
-		error("Unexpected length");
-	    err = ncmpi_get_att_text(ncid_out, i, "a", &value);
-	    IF (err != NC_NOERR)
-		error("ncmpi_get_att_text: %s", ncmpi_strerror(err));
-	    IF (value != 'A')
-		error("Unexpected value");
-	}                                                   
-    }                                                   
-
-    err = ncmpi_close(ncid_out);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_rename_att
- *    try with bad netCDF handle, check error
- *    try with bad variable handle, check error
- *    try with nonexisting att name, check error
- *    try renaming to existing att name, check error
- *    check that proper rename worked with ncmpi_inq_attid
- *    try in data mode, check error
- */
-int
-test_ncmpi_rename_att(void)
-{
-    int ncid;
-    int varid;
-    int err;
-    int i;
-    int j;
-    MPI_Offset  k;
-    int attnum;
-    char *attname;
-    char name[NC_MAX_NAME];
-    char oldname[NC_MAX_NAME];
-    char newname[NC_MAX_NAME];
-    int nok = 0;      /* count of valid comparisons */
-    nc_type datatype;
-    nc_type atttype;
-    MPI_Offset length;
-    size_t attlength;
-    char  text[MAX_NELS];
-    double value[MAX_NELS];
-    double expect;
-
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    err = ncmpi_rename_att(ncid, BAD_VARID, "abc", "newName");
-    IF (err != NC_ENOTVAR)
-	error("bad var id: status = %d", err);
-    ELSE_NOK
-    def_dims(ncid);
-    def_vars(ncid);
-    put_atts(ncid);
-
-    for (i = -1; i < numVars; i++) {
-        varid = VARID(i);
-        for (j = 0; j < NATTS(i); j++) {
-	    attname = ATT_NAME(i,j);
-	    err = ncmpi_rename_att(BAD_ID, varid, attname, "newName");
-	    IF (err != NC_EBADID)
-		error("bad ncid: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_rename_att(ncid, varid, "noSuch", "newName");
-	    IF (err != NC_ENOTATT)
-		error("bad attname: status = %d", err);
-            ELSE_NOK
-	    strcpy(newname, "new_");
-	    strcat(newname, attname);
-	    err = ncmpi_rename_att(ncid, varid, attname, newname);
-	    IF (err != NC_NOERR)
-		error("ncmpi_rename_att: %s", ncmpi_strerror(err));
-            ELSE_NOK
-	    err = ncmpi_inq_attid(ncid, varid, newname, &attnum);
-	    IF (err != NC_NOERR)
-		error("ncmpi_inq_attid: %s", ncmpi_strerror(err));
-	    IF (attnum != j)
-		error("Unexpected attnum");
-	}
-    }
-
-    /* Close. Reopen & check */
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_open(comm, scratch, NC_WRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-
-    for (i = -1; i < numVars; i++) {
-        varid = VARID(i);
-        for (j = 0; j < NATTS(i); j++) {
-	    attname = ATT_NAME(i,j);
-	    atttype = ATT_TYPE(i,j);
-	    attlength = ATT_LEN(i,j);
-            strcpy(newname, "new_");
-            strcat(newname, attname);
-            err = ncmpi_inq_attname(ncid, varid, j, name);
-            IF (err != NC_NOERR)
-                error("ncmpi_inq_attname: %s", ncmpi_strerror(err));
-            IF (strcmp(name, newname) != 0)
-                error("ncmpi_inq_attname: unexpected name");
-            err = ncmpi_inq_att(ncid, varid, name, &datatype, &length);
-            IF (err != NC_NOERR)
-                error("ncmpi_inq_att: %s", ncmpi_strerror(err));
-            IF (datatype != atttype)
-                error("ncmpi_inq_att: unexpected type");
-            IF (length != attlength)
-                error("ncmpi_inq_att: unexpected length");
-            if (datatype == NC_CHAR) {
-                err = ncmpi_get_att_text(ncid, varid, name, text);
-                IF (err != NC_NOERR)
-                    error("ncmpi_get_att_text: %s", ncmpi_strerror(err));
-                for (k = 0; k < attlength; k++) {
-                    expect = hash(datatype, -1, &k);
-                    IF (text[k] != (char)expect)
-                        error("ncmpi_get_att_text: unexpected value");
-                }
-            } else {
-                err = ncmpi_get_att_double(ncid, varid, name, value);
-                IF (err != NC_NOERR)
-                    error("ncmpi_get_att_double: %s", ncmpi_strerror(err));
-                for (k = 0; k < attlength; k++) {
-                    expect = hash(datatype, -1, &k);
-		    if (inRange(expect, datatype)) {
-			IF (!equal(value[k],expect,datatype,NCT_DOUBLE))
-			    error("ncmpi_get_att_double: unexpected value");
-                    }
-                }
-            }
-        }
-    }
-
-	/* Now in data mode */
-	/* Try making names even longer. Then restore original names */
-
-    for (i = -1; i < numVars; i++) {
-        varid = VARID(i);
-        for (j = 0; j < NATTS(i); j++) {
-	    attname = ATT_NAME(i,j);
-	    strcpy(oldname, "new_");
-	    strcat(oldname, attname);
-	    strcpy(newname, "even_longer_");
-	    strcat(newname, attname);
-	    err = ncmpi_rename_att(ncid, varid, oldname, newname);
-	    IF (err != NC_ENOTINDEFINE)
-		error("longer name in data mode: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_rename_att(ncid, varid, oldname, attname);
-	    IF (err != NC_NOERR)
-		error("ncmpi_rename_att: %s", ncmpi_strerror(err));
-            ELSE_NOK
-	    err = ncmpi_inq_attid(ncid, varid, attname, &attnum);
-	    IF (err != NC_NOERR)
-		error("ncmpi_inq_attid: %s", ncmpi_strerror(err));
-	    IF (attnum != j)
-		error("Unexpected attnum");
-	}
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_del_att
- *    try with bad netCDF handle, check error
- *    try with bad variable handle, check error
- *    try with nonexisting att name, check error
- *    check that proper delete worked using:
- *      ncmpi_inq_attid, ncmpi_inq_natts, ncmpi_inq_varnatts
- */
-int
-test_ncmpi_del_att(void)
-{
-    int ncid;
-    int err, nok=0;
-    int i;
-    int j;
-    int attnum;
-    int natts;
-    int numatts;
-    int varid;
-    char *name;                 /* of att */
-
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    err = ncmpi_del_att(ncid, BAD_VARID, "abc");
-    IF (err != NC_ENOTVAR)
-	error("bad var id: status = %d", err);
-    ELSE_NOK
-    def_dims(ncid);
-    def_vars(ncid);
-    put_atts(ncid);
-
-    for (i = -1; i < numVars; i++) {
-	varid = VARID(i);
-	numatts = NATTS(i);
-        for (j = 0; j < numatts; j++) {
-	    name = ATT_NAME(i,j);
-	    err = ncmpi_del_att(BAD_ID, varid, name);
-	    IF (err != NC_EBADID)
-		error("bad ncid: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_del_att(ncid, varid, "noSuch");
-	    IF (err != NC_ENOTATT)
-		error("bad attname: status = %d", err);
-            ELSE_NOK
-	    err = ncmpi_del_att(ncid, varid, name);
-	    IF (err != NC_NOERR)
-		error("ncmpi_del_att: %s", ncmpi_strerror(err));
-            ELSE_NOK
-	    err = ncmpi_inq_attid(ncid, varid, name, &attnum);
-	    IF (err != NC_ENOTATT)
-		error("bad attname: status = %d", err);
-	    if (i < 0) {
-		err = ncmpi_inq_natts(ncid, &natts);
-		IF (err != NC_NOERR)
-		    error("ncmpi_inq_natts: %s", ncmpi_strerror(err));
-		IF (natts != numatts-j-1)
-		    error("natts: expected %d, got %d", numatts-j-1, natts);
-	    }
-	    err = ncmpi_inq_varnatts(ncid, varid, &natts);
-	    IF (err != NC_NOERR)
-		error("ncmpi_inq_natts: %s", ncmpi_strerror(err));
-	    IF (natts != numatts-j-1)
-		error("natts: expected %d, got %d", numatts-j-1, natts);
-	}
-    }
-
-        /* Close. Reopen & check no attributes left */
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_open(comm, scratch, NC_WRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_inq_natts(ncid, &natts);
-    IF (err != NC_NOERR)
-	error("ncmpi_inq_natts: %s", ncmpi_strerror(err));
-    IF (natts != 0)
-	error("natts: expected %d, got %d", 0, natts);
-    for (i = -1; i < numVars; i++) {
-	varid = VARID(i);
-	err = ncmpi_inq_varnatts(ncid, varid, &natts);
-	IF (err != NC_NOERR)
-	    error("ncmpi_inq_natts: %s", ncmpi_strerror(err));
-	IF (natts != 0)
-	    error("natts: expected %d, got %d", 0, natts);
-    }
-
-	/* restore attributes. change to data mode. try to delete */
-    err = ncmpi_redef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_redef: %s", ncmpi_strerror(err));
-    put_atts(ncid);
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-
-    for (i = -1; i < numVars; i++) {
-	varid = VARID(i);
-	numatts = NATTS(i);
-        for (j = 0; j < numatts; j++) {
-	    name = ATT_NAME(i,j);
-	    err = ncmpi_del_att(ncid, varid, name);
-	    IF (err != NC_ENOTINDEFINE)
-		error("in data mode: status = %d", err);
-            ELSE_NOK
-	}
-    }
-
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-/*
- * Test ncmpi_set_fill
- *    try with bad netCDF handle, check error
- *    try in read-only mode, check error
- *    try with bad new_fillmode, check error
- *    try in data mode, check error
- *    check that proper set to NC_FILL works for record & non-record variables
- *    (note that it is not possible to test NC_NOFILL mode!)
- *    close file & create again for test using attribute _FillValue
- */
-int
-test_ncmpi_set_fill(void)
-{
-    int ncid;
-    int varid;
-    int err;
-    int i;
-    int j;
-    int old_fillmode;
-    int nok = 0;      /* count of valid comparisons */
-    char text = 0;
-    double value = 0;
-    double fill;
-    MPI_Offset index[MAX_RANK];
-
-	/* bad ncid */
-    err = ncmpi_set_fill(BAD_ID, NC_NOFILL, &old_fillmode);
-    IF (err != NC_EBADID)
-	error("bad ncid: status = %d", err);
-
-	/* try in read-only mode */
-    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_open: %s", ncmpi_strerror(err));
-    err = ncmpi_set_fill(ncid, NC_NOFILL, &old_fillmode);
-    IF (err != NC_EPERM)
-	error("read-only: status = %d", err);
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-
-	/* create scratch */
-    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-
-	/* BAD_FILLMODE */
-    err = ncmpi_set_fill(ncid, BAD_FILLMODE, &old_fillmode);
-    IF (err != NC_EINVAL)
-        error("bad fillmode: status = %d", err);
-
-	/* proper calls */
-    err = ncmpi_set_fill(ncid, NC_NOFILL, &old_fillmode);
-    IF (err != NC_NOERR)
-        error("ncmpi_set_fill: %s", ncmpi_strerror(err));
-    IF (old_fillmode != NC_NOFILL)
-        error("Unexpected old fill mode: %d", old_fillmode);
-    err = ncmpi_set_fill(ncid, NC_FILL, &old_fillmode);
-    IF (err != NC_NOERR)
-        error("ncmpi_set_fill: %s", ncmpi_strerror(err));
-    IF (old_fillmode != NC_NOFILL)
-        error("Unexpected old fill mode: %d", old_fillmode);
-
-	/* define dims & vars */
-    def_dims(ncid);
-    def_vars(ncid);
-
-	/* Change to data mode. Set fillmode again */
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    err = ncmpi_set_fill(ncid, NC_FILL, &old_fillmode);
-    IF (err != NC_ENOTINDEFINE)
-        error("ncmpi_set_fill: %s", ncmpi_strerror(err));
-
-	/* Write record number NRECS to force writing of preceding records */
-	/* Assumes variable cr is char vector with UNLIMITED dimension */
-    err = ncmpi_inq_varid(ncid, "cr", &varid);
-    IF (err != NC_NOERR)
-        error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
-    index[0] = NRECS;
-    for (i=0; i<=index[0]; i++)
-        err = ncmpi_fill_var_rec(ncid, varid, i);
-    err = ncmpi_put_var1_text_all(ncid, varid, index, &text);
-    IF (err != NC_NOERR)
-        error("ncmpi_put_var1_text_all: %s", ncmpi_strerror(err));
-
-	/* get all variables & check all values equal default fill */
-    for (i = 0; i < numVars; i++) {
-        if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */
-	switch (var_type[i]) {
-	    case NC_CHAR:   fill = NC_FILL_CHAR; break;
-	    case NC_BYTE:   fill = NC_FILL_BYTE; break;
-	    case NC_SHORT:  fill = NC_FILL_SHORT; break;
-	    case NC_INT:   fill = NC_FILL_INT; break;
-	    case NC_FLOAT:  fill = NC_FILL_FLOAT; break;
-	    case NC_DOUBLE: fill = NC_FILL_DOUBLE; break;
-	    case NC_UBYTE: fill = NC_FILL_UBYTE; break;
-	    case NC_USHORT: fill = NC_FILL_USHORT; break;
-	    case NC_UINT: fill = NC_FILL_UINT; break;
-	    case NC_INT64: fill = NC_FILL_INT64; break;
-	    case NC_UINT64: fill = NC_FILL_UINT64; break;
-	    default: assert(0);
-	}
-	for (j = 0; j < var_nels[i]; j++) {
-            err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR)
-                error("error in toMixedBase");
-	    if (var_type[i] == NC_CHAR) {
-		err = ncmpi_get_var1_text_all(ncid, i, index, &text);
-		IF (err != NC_NOERR)
-		    error("ncmpi_get_var1_text_all failed: %s", ncmpi_strerror(err));
-		value = text;
-	    } else {
-		err = ncmpi_get_var1_double_all(ncid, i, index, &value);
-		IF (err != NC_NOERR)
-		    error("ncmpi_get_var1_double_all failed: %s", ncmpi_strerror(err));
-	    }
-	    IF (value != fill && fabs((fill - value)/fill) > DBL_EPSILON)
-		error("\n\t\t%s Value expected: %-23.17e,\n\t\t          read: %-23.17e\n",
-			var_name[i],fill, value);
-	    ELSE_NOK
-        }
-    }
-
-	/* close scratch & create again for test using attribute _FillValue */
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR) {
-        error("ncmpi_create: %s", ncmpi_strerror(err));
-        return nok;
-    }
-    def_dims(ncid);
-    def_vars(ncid);
-
-	/* set _FillValue = 42 for all vars */
-    text = fill = 42;
-    for (i = 0; i < numVars; i++) {
-	if (var_type[i] == NC_CHAR) {
-	    err = ncmpi_put_att_text(ncid, i, "_FillValue", 1, &text);
-	    IF (err != NC_NOERR)
-		error("ncmpi_put_att_text: %s", ncmpi_strerror(err));
-	} else {
-	    err = ncmpi_put_att_double(ncid, i, "_FillValue",var_type[i],1,&fill);
-	    IF (err != NC_NOERR)
-		error("ncmpi_put_att_double: %s", ncmpi_strerror(err));
-	}
-    }
-
-	/* data mode. write records */
-    err = ncmpi_enddef(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_enddef: %s", ncmpi_strerror(err));
-    index[0] = NRECS;
-    for (i=0; i<=index[0]; i++)
-        err = ncmpi_fill_var_rec(ncid, varid, i);
-    err = ncmpi_put_var1_text_all(ncid, varid, index, &text);
-    IF (err != NC_NOERR)
-        error("ncmpi_put_var1_text_all: %s", ncmpi_strerror(err));
-
-	/* get all variables & check all values equal 42 */
-    for (i = 0; i < numVars; i++) {
-        if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */
-	for (j = 0; j < var_nels[i]; j++) {
-            err = toMixedBase(j, var_rank[i], var_shape[i], index);
-            IF (err != NC_NOERR)
-                error("error in toMixedBase");
-	    if (var_type[i] == NC_CHAR) {
-		err = ncmpi_get_var1_text_all(ncid, i, index, &text);
-		IF (err != NC_NOERR)
-		    error("ncmpi_get_var1_text_all failed: %s", ncmpi_strerror(err));
-		value = text;
-	    } else {
-		err = ncmpi_get_var1_double_all(ncid, i, index, &value);
-		IF (err != NC_NOERR)
-		    error("ncmpi_get_var1_double_all failed: %s", ncmpi_strerror(err));
-	    }
-	    IF (value != fill)
-		error(" %s Value expected: %g, read: %g\n", var_name[i],fill, value);
-	    ELSE_NOK
-        }
-    }
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-        error("remove of %s failed", scratch);
-
-    return nok;
-}
-
-
-/* This function gets the version of a netCDF file, 1 is for netCDF
-   classic, 2 for 64-bit offset format, (someday) 3 for HDF5 format.
-*/
-#define MAGIC_NUM_LEN 4
-static
-int ncmpi_get_file_version(char *path, int *version)
-{
-   FILE *fp;
-   char magic[MAGIC_NUM_LEN];
-
-   /* Need two valid pointers - check for NULL. */
-   if (!version || !path)
-      return NC_EINVAL;
-
-   /* Figure out if this is a netcdf or hdf5 file. */
-   if (!(fp = fopen(path, "r")) ||
-       fread(magic, MAGIC_NUM_LEN, 1, fp) != 1)
-      return errno;
-   fclose(fp);
-   if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0)
-   {
-      if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC || 
-         magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF2 ||
-         magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF2)
-        *version = magic[MAGIC_NUM_LEN-1];
-      else
-        return NC_ENOTNC;
-   }
-   /*   tomorrow, tomorrow, I love you tomorrow, you're always a day
-       away! */
-   /*if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
-      *version = 3;*/
-   return NC_NOERR;
-}
-
-/*
- * Test nc_set_default_format
- *    try with bad default format
- *    try with NULL old_formatp
- *    try in data mode, check error
- *    check that proper set to NC_FILL works for record & non-record variables
- *    (note that it is not possible to test NC_NOFILL mode!)
- *    close file & create again for test using attribute _FillValue
- */
-int
-test_ncmpi_set_default_format(void)
-{
-    int ncid, nok=0;
-    int err;
-    int i;
-    int version=1;
-    int old_format;
-
-    /* bad format */
-    err = ncmpi_set_default_format(BAD_DEFAULT_FORMAT, &old_format);
-    IF (err != NC_EINVAL)
-       error("bad default format: status = %d", err);
-    ELSE_NOK
-
-    /* NULL old_formatp */
-    err = ncmpi_set_default_format(NC_FORMAT_CDF2, NULL);
-    IF (err != NC_NOERR)
-       error("null old_fortmatp: status = %d", err);
-    ELSE_NOK
-
-    /* Cycle through available formats. */
-    for(i=1; i<5; i++)
-    {
-       if (i == 3 || i == 4) continue; /* test classic formats only */
-
-       if ((err = ncmpi_set_default_format(i, NULL)))
-         error("setting classic format: status = %d", err);
-       ELSE_NOK
-       if ((err=ncmpi_create(comm, scratch, NC_CLOBBER, info, &ncid)))
-         error("bad nc_create: status = %d", err);
-       if ((err=ncmpi_put_att_text(ncid, NC_GLOBAL, "testatt", 
-                               sizeof("blah"), "blah")))
-         error("bad put_att: status = %d", err);
-       if ( (err=ncmpi_close(ncid)))
-         error("bad close: status = %d", err);
-       if ( (err = ncmpi_get_file_version(scratch, &version)) )
-         error("bad file version = %d", err);
-       if (version != i) {
-          if (i == 4) {
-              if (version == 3) continue;
-              printf("expect version 3 but got %d (file=%s)",version,scratch);
-              continue;
-          }
-          printf("expect version %d but got %d (file=%s)",i,version,scratch);
-          error("bad file version = %d", version);
-        }
-    }
-
-    /* Remove the left-over file. */
-    if ((err = ncmpi_delete(scratch, info)))
-       error("remove of %s failed", scratch);
-    return nok;
-}
-
-
-
-
-/*
- * Test ncmpi_delete
- * 	create netcdf file 'scratch.nc' with no data, close it
- * 	delete the file
- */
-int
-test_ncmpi_delete(void)
-{
-    int err, nok=0;;
-    int ncid;
-
-    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
-    IF (err != NC_NOERR)
-	error("error creating scratch file %s, status = %d\n", scratch,err);
-    err = ncmpi_close(ncid);
-    IF (err != NC_NOERR)
-        error("ncmpi_close: %s", ncmpi_strerror(err));
-    err = ncmpi_delete(scratch, info);
-    IF (err != NC_NOERR)
-	error("remove of %s failed", scratch);
-    ELSE_NOK
-    return nok;
-}
diff --git a/test/nc_test/test_write.m4 b/test/nc_test/test_write.m4
new file mode 100644
index 0000000..76f0c6e
--- /dev/null
+++ b/test/nc_test/test_write.m4
@@ -0,0 +1,2503 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl This file is supposed to be the same as PnetCDF's test_write.m4
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: test_write.m4 2621 2016-11-15 17:35:22Z wkliao $ */
+
+dnl
+dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
+dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types
+dnl (MPI_Offset vs. size_t), and function name substrings for external data
+dnl types.
+dnl
+
+#include <sys/types.h>  /* open() */
+#include <sys/stat.h>   /* open() */
+#include <fcntl.h>      /* open() */
+#include <unistd.h>     /* read() */
+
+#include "tests.h"
+#include "math.h"
+
+define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl
+
+define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl
+define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl
+define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_$1',`test_nc_$1')')dnl
+define(`APIFunc', `ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl
+
+define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, $3)', `file_open($1, $2, $3)')')dnl
+define(`FileCreate',`ifdef(`PNETCDF',`ncmpi_create(comm, $1, $2, info, $3)', `file_create($1, $2, $3)')')dnl
+define(`FileDelete',`ifdef(`PNETCDF',`ncmpi_delete($1,$2)',`nc_delete($1)')')dnl
+
+define(`Def_Vars',  `ifdef(`PNETCDF',`def_vars($1,$2)',`def_vars($1)')')dnl
+define(`Put_Atts',  `ifdef(`PNETCDF',`put_atts($1,$2,$3)',`put_atts($1)')')dnl
+define(`Put_Vars',  `ifdef(`PNETCDF',`put_vars($1,$2)',`put_vars($1)')')dnl
+define(`Check_File',`ifdef(`PNETCDF',`check_file($1,$2,$3)',`check_file($1)')')dnl
+define(`Check_Atts',`ifdef(`PNETCDF',`check_atts($1,$2,$3)',`check_atts($1)')')dnl
+define(`Check_Vars',`ifdef(`PNETCDF',`check_vars($1,$2)',`check_vars($1)')')dnl
+define(`VarArgs',   `ifdef(`PNETCDF',`int numVars',`void')')dnl
+define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts, int numVars',`void')')dnl
+
+define(`GetVar1TYPE',`ifdef(`PNETCDF',`ncmpi_get_var1_$1_all',`nc_get_var1_$1')')dnl
+define(`PutVar1TYPE',`ifdef(`PNETCDF',`ncmpi_put_var1_$1_all',`nc_put_var1_$1')')dnl
+
+define(`PutVar1', `ifdef(`PNETCDF',`ncmpi_put_var1_all($1,$2,$3,$4,$5,$6)',          `nc_put_var1($1,$2,$3,$4)')')dnl
+define(`PutVar',  `ifdef(`PNETCDF',`ncmpi_put_var_all( $1,$2,$3,$4,$5)',             `nc_put_var( $1,$2,$3)')')dnl
+define(`PutVara', `ifdef(`PNETCDF',`ncmpi_put_vara_all($1,$2,$3,$4,$5,$6,$7)',       `nc_put_vara($1,$2,$3,$4,$5)')')dnl
+define(`PutVars', `ifdef(`PNETCDF',`ncmpi_put_vars_all($1,$2,$3,$4,$5,$6,$7,$8)',    `nc_put_vars($1,$2,$3,$4,$5,$6)')')dnl
+define(`PutVarm', `ifdef(`PNETCDF',`ncmpi_put_varm_all($1,$2,$3,$4,$5,$6,$7,$8,$9)', `nc_put_varm($1,$2,$3,$4,$5,$6,$7)')')dnl
+
+
+/*
+ * Test APIFunc(create)
+ *    For mode in NC_NOCLOBBER, NC_CLOBBER do:
+ *       create netcdf file 'scratch.nc' with no data, close it
+ *       test that it can be opened, do APIFunc(inq) to check nvars = 0, etc.
+ *    Try again in NC_NOCLOBBER mode, check error return
+ * On exit, delete this file
+ */
+int
+TestFunc(create)(void)
+{
+    int clobber; /* 0 for NC_NOCLOBBER, 1 for NC_CLOBBER */
+    int err;
+    int ncid;
+    int ndims;   /* number of dimensions */
+    int nvars;   /* number of variables */
+    int ngatts;  /* number of global attributes */
+    int recdim;  /* id of unlimited dimension */
+    int nok=0;
+
+    for (clobber = 0; clobber < 2; clobber++) {
+        err = FileCreate(scratch, clobber ? NC_CLOBBER : NC_NOCLOBBER, &ncid);
+        IF (err != NC_NOERR)
+            error("create: %s", APIFunc(strerror)(err));
+        ELSE_NOK
+        err = APIFunc(close)(ncid);
+        IF (err != NC_NOERR)
+            error("close: %s", APIFunc(strerror)(err));
+        err = FileOpen(scratch, NC_NOWRITE, &ncid);
+        IF (err != NC_NOERR)
+            error("open: %s", APIFunc(strerror)(err));
+        err = APIFunc(inq)(ncid, &ndims, &nvars, &ngatts, &recdim);
+        IF (err != NC_NOERR)
+            error("inq: %s", APIFunc(strerror)(err));
+        else IF (ndims != 0)
+            error("inq: wrong number of dimensions returned, %d", ndims);
+        else IF (nvars != 0)
+            error("inq: wrong number of variables returned, %d", nvars);
+        else IF (ngatts != 0)
+            error("inq: wrong number of global atts returned, %d", ngatts);
+        else IF (recdim != -1)
+            error("inq: wrong record dimension ID returned, %d", recdim);
+        ELSE_NOK
+        err = APIFunc(close)(ncid);
+        IF (err != NC_NOERR)
+            error("close: %s", APIFunc(strerror)(err));
+    }
+
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_EEXIST)
+        error("expecting NC_EEXIST but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(redef)
+ * (In fact also tests APIFunc(enddef) - called from TestFunc(enddef))
+ *    BAD_ID
+ *    attempt redef (error) & enddef on read-only file
+ *    create file, define dims & vars.
+ *    attempt put var (error)
+ *    attempt redef (error) & enddef.
+ *    put vars
+ *    attempt def new dims (error)
+ *    redef
+ *    def new dims, vars.
+ *    put atts
+ *    enddef
+ *    put vars
+ *    close
+ *    check file: vars & atts
+ *    check reopening with NC_WRITE and adding new dims, atts, vars
+ */
+int
+TestFunc(redef)(AttVarArgs)
+{
+    int ncid;          /* netcdf id */
+    /* used to force effective test of ncio->move() in redef */
+    IntType sizehint = 8192;
+    int dimid;         /* dimension id */
+    int varid;         /* variable id */
+    int varid1;        /* variable id */
+    int nok=0, err;
+    const char * title = "Not funny";
+    double var;
+    char name[NC_MAX_NAME];
+    IntType length;
+    int fmt_variant1, fmt_variant2;
+
+    /* BAD_ID tests */
+    err = APIFunc(redef)(BAD_ID);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(enddef)(BAD_ID);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* read-only tests */
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(redef)(ncid);
+    IF (err != NC_EPERM)
+        error("expecting NC_EPERM but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_ENOTINDEFINE)
+        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    /* tests using scratch file */
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    /* limit for ncio implementations which have infinite chunksize */
+    if(sizehint > 32768)
+        sizehint = 16384;
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+    Put_Atts(ncid, numGatts, numVars);
+    err = APIFunc(inq_varid)(ncid, "d", &varid);
+    IF (err != NC_NOERR)
+        error("inq_varid: %s", APIFunc(strerror)(err));
+    var = 1.0;
+
+ifdef(`PNETCDF', `
+    err = ncmpi_begin_indep_data(ncid);
+    IF (err != NC_EINDEFINE)
+        error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err));')dnl
+
+    err = PutVar1TYPE(double)(ncid, varid, NULL, &var);
+    IF (err != NC_EINDEFINE)
+        error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err));
+
+ifdef(`PNETCDF', `
+    err = ncmpi_end_indep_data(ncid);
+    IF (err != NC_ENOTINDEP)
+        error("expecting NC_ENOTINDEP but got %s", nc_err_code_name(err));')dnl
+
+    err = APIFunc(redef)(ncid);
+    IF (err != NC_EINDEFINE)
+        error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    Put_Vars(ncid, numVars);
+    err = APIFunc(def_dim)(ncid, "abc", sizehint, &dimid);
+    IF (err != NC_ENOTINDEFINE)
+        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
+    err = APIFunc(redef)(ncid);
+    IF (err != NC_NOERR)
+        error("redef: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+
+    err = APIFunc(set_fill)(ncid, NC_NOFILL, NULL);
+    IF (err != NC_NOERR)
+        error("set_fill: %s", APIFunc(strerror)(err));
+
+    err = APIFunc(def_dim)(ncid, "abc", sizehint, &dimid);
+    IF (err != NC_NOERR)
+        error("def_dim: %s", APIFunc(strerror)(err));
+    err = APIFunc(def_var)(ncid, "abcScalar", NC_INT, 0, NULL, &varid);
+    IF (err != NC_NOERR)
+        error("def_var: %s", APIFunc(strerror)(err));
+    err = APIFunc(def_var)(ncid, "abc", NC_INT, 1, &dimid, &varid1);
+    IF (err != NC_NOERR)
+        error("def_var: %s", APIFunc(strerror)(err));
+    {
+        int dimids[NDIMS +1];
+        int ii = 0;
+        for(ii = 0; ii < NDIMS; ii++) dimids[ii] = ii;
+        dimids[NDIMS] = dimid;
+        err = APIFunc(def_var)(ncid, "abcRec", NC_INT, NDIMS, dimids, &varid1);
+        IF (err != NC_NOERR)
+            error("def_var: %s", APIFunc(strerror)(err));
+    }
+    err = APIFunc(put_att_text)(ncid, NC_GLOBAL, "title", 1+strlen(title), title);
+    IF (err != NC_NOERR)
+        error("put_att_text: %s", APIFunc(strerror)(err));
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    var = 1.0;
+
+ifdef(`PNETCDF', `
+    err = ncmpi_end_indep_data(ncid);
+    IF (err != NC_ENOTINDEP)
+        error("expecting NC_ENOTINDEP but got %s", nc_err_code_name(err));')dnl
+
+    err = PutVar1TYPE(double)(ncid, varid, NULL, &var);
+    IF (err != NC_NOERR)
+        error("put_var1_double: %s", APIFunc(strerror)(err));
+    err = APIFunc(inq_format)(ncid, &fmt_variant1);
+    IF (err)
+        error("inq_format: %s", APIFunc(strerror)(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    /* check scratch file written as expected */
+    Check_File(scratch, numGatts, numVars); /* checks all except "abc" stuff added above */
+
+    IF ((err = FileOpen(scratch, NC_NOWRITE, &ncid)))
+        error("open: %s", APIFunc(strerror)(err));
+    IF ((err = APIFunc(inq_dim)(ncid, dimid, name, &length)))
+        error("inq_dim: %s", APIFunc(strerror)(err));
+    IF (strcmp(name, "abc") != 0)
+        error("Unexpected dim name");
+    IF (length != sizehint)
+        error("Unexpected dim length");
+    IF ((err = GetVar1TYPE(double)(ncid, varid, NULL, &var)))
+        error("get_var1_double: %s", APIFunc(strerror)(err));
+    IF (var != 1.0)
+        error("get_var1_double: unexpected value");
+    IF ((err = APIFunc(close)(ncid)))
+        error("close: %s", APIFunc(strerror)(err));
+
+    /* open scratch file for writing, add another dim, var, att, then check */
+    IF ((err = FileOpen(scratch, NC_WRITE, &ncid)))
+        error("open: %s", APIFunc(strerror)(err));
+    IF ((err = APIFunc(redef)(ncid)))
+        error("redef: %s", APIFunc(strerror)(err));
+    IF ((err = APIFunc(def_dim)(ncid, "def", sizehint, &dimid)))
+        error("def_dim: %s", APIFunc(strerror)(err));
+    IF ((err = APIFunc(def_var)(ncid, "defScalar", NC_INT, 0, NULL, &varid)))
+        error("def_var: %s", APIFunc(strerror)(err));
+    IF ((err = APIFunc(def_var)(ncid, "def", NC_INT, 1, &dimid, &varid1)))
+        error("def_var: %s", APIFunc(strerror)(err));
+    IF ((err = APIFunc(put_att_text)(ncid, NC_GLOBAL, "Credits", 1+strlen("Thanks!"), "Thanks!")))
+        error("put_att_text: %s", APIFunc(strerror)(err));
+    IF ((err = APIFunc(enddef)(ncid)))
+        error("enddef: %s", APIFunc(strerror)(err));
+    var = 2.0;
+    IF ((err = PutVar1TYPE(double)(ncid, varid, NULL, &var)))
+        error("put_var1_double: %s", APIFunc(strerror)(err));
+    IF ((err = APIFunc(close)(ncid)))
+        error("close: %s", APIFunc(strerror)(err));
+
+    /* check scratch file written as expected */
+    Check_File(scratch, numGatts, numVars);
+
+    err = FileOpen(scratch, NC_NOWRITE, &ncid);
+    IF (err)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(inq_dim)(ncid, dimid, name, &length);
+    IF (err)
+        error("inq_dim: %s", APIFunc(strerror)(err));
+    IF (strcmp(name, "def") != 0)
+        error("Unexpected dim name");
+    IF (length != sizehint)
+        error("Unexpected dim length");
+    err = GetVar1TYPE(double)(ncid, varid, NULL, &var);
+    IF (err)
+        error("get_var1_double: %s", APIFunc(strerror)(err));
+    IF (var != 2.0)
+        error("get_var1_double: unexpected value");
+    /* make sure format variant hasn't changed from when created */
+    err = APIFunc(inq_format)(ncid, &fmt_variant2);
+    IF (err)
+        error("inq_format: %s", APIFunc(strerror)(err));
+    IF (fmt_variant1 != fmt_variant2)
+        error("enddef changed format variant");
+    err = APIFunc(close)(ncid);
+    IF (err)
+        error("close: %s", APIFunc(strerror)(err));
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(enddef)
+ * Simply calls TestFunc(redef) which tests both APIFunc(redef) & APIFunc(enddef)
+ */
+int
+TestFunc(enddef)(AttVarArgs)
+{
+    ifdef(`PNETCDF',
+    `return test_ncmpi_redef(numGatts, numVars);',
+    `return test_nc_redef();')
+}
+
+
+/*
+ * Test APIFunc(sync)
+ *    try with bad handle, check error
+ *    try in define mode, check error
+ *    try writing with one handle, reading with another on same netCDF
+ */
+int
+TestFunc(sync)(AttVarArgs)
+{
+    int ncidw;         /* netcdf id for writing */
+    int ncidr;         /* netcdf id for reading */
+    int nok=0, err;
+
+    /* BAD_ID test */
+    err = APIFunc(sync)(BAD_ID);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* create scratch file & try APIFunc(sync) in define mode */
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncidw);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    err = APIFunc(sync)(ncidw);
+    IF (err != NC_EINDEFINE)
+        error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* write using same handle */
+    def_dims(ncidw);
+    Def_Vars(ncidw, numVars);
+    Put_Atts(ncidw, numGatts, numVars);
+    err = APIFunc(enddef)(ncidw);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    Put_Vars(ncidw, numVars);
+    err = APIFunc(sync)(ncidw);
+    IF (err != NC_NOERR)
+        error("sync of ncidw failed: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+
+    /* open another handle, APIFunc(sync), read (check) */
+    err = FileOpen(scratch, NC_NOWRITE, &ncidr);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(sync)(ncidr);
+    IF (err != NC_NOERR)
+        error("sync of ncidr failed: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    check_dims(ncidr);
+    Check_Atts(ncidr, numGatts, numVars);
+    Check_Vars(ncidr, numVars);
+
+    /* close both handles */
+    err = APIFunc(close)(ncidr);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = APIFunc(close)(ncidw);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(abort)
+ *    try with bad handle, check error
+ *    try in define mode before anything written, check that file was deleted
+ *    try after APIFunc(enddef), APIFunc(redef), define new dims, vars, atts
+ *    try after writing variable
+ */
+int
+TestFunc(abort)(AttVarArgs)
+{
+    int ncid;          /* netcdf id */
+    int err;
+    int ndims;
+    int nvars;
+    int ngatts;
+    int nok=0;
+
+    /* BAD_ID test */
+    err = APIFunc(abort)(BAD_ID);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* create scratch file & try APIFunc(abort) in define mode */
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+    Put_Atts(ncid, numGatts, numVars);
+    err = APIFunc(abort)(ncid);
+    IF (err != NC_NOERR)
+        error("abort of ncid failed: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    err = APIFunc(close)(ncid);        /* should already be closed */
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    err = FileDelete(scratch, info);        /* should already be deleted */
+ifdef(`PNETCDF',
+    `IF (err != NC_ENOENT && err != NC_EFILE)
+        error("expecting NC_ENOENT or NC_EFILE but got %s", nc_err_code_name(err));',
+    `IF (err != ENOENT && err != NC_EIO)
+        error("expecting ENOENT or NC_EIO but got %s", nc_err_code_name(err));')dnl
+
+    /*
+     * create scratch file
+     * do APIFunc(enddef) & APIFunc(redef)
+     * define new dims, vars, atts
+     * try APIFunc(abort): should restore previous state (no dims, vars, atts)
+     */
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    err = APIFunc(redef)(ncid);
+    IF (err != NC_NOERR)
+        error("redef: %s", APIFunc(strerror)(err));
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+    Put_Atts(ncid, numGatts, numVars);
+    err = APIFunc(abort)(ncid);
+    IF (err != NC_NOERR)
+        error("abort of ncid failed: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    err = APIFunc(close)(ncid);        /* should already be closed */
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    err = FileOpen(scratch, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(inq)(ncid, &ndims, &nvars, &ngatts, NULL);
+    IF (err != NC_NOERR)
+        error("inq: %s", APIFunc(strerror)(err));
+    IF (ndims != 0)
+        error("ndims should be 0");
+    IF (nvars != 0)
+        error("nvars should be 0");
+    IF (ngatts != 0)
+        error("ngatts should be 0");
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    /* try APIFunc(abort) in data mode - should just close */
+    err = FileCreate(scratch, NC_CLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+    Put_Atts(ncid, numGatts, numVars);
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    Put_Vars(ncid, numVars);
+    err = APIFunc(abort)(ncid);
+    IF (err != NC_NOERR)
+        error("abort of ncid failed: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    err = APIFunc(close)(ncid);       /* should already be closed */
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    Check_File(scratch, numGatts, numVars);
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(def_dim)
+ *    try with bad netCDF handle, check error
+ *    try in data mode, check error
+ *    check that returned id is one more than previous id
+ *    try adding same dimension twice, check error
+ *    try with illegal sizes, check error
+ *    make sure unlimited size works, shows up in APIFunc(inq_unlimdim)
+ *    try to define a second unlimited dimension, check error
+ */
+int
+TestFunc(def_dim)(VarArgs)
+{
+    int ncid;
+    int  err;           /* status */
+    int  i, nok=0;
+    int  dimid;         /* dimension id */
+    IntType length;
+
+    /* BAD_ID test */
+    err = APIFunc(def_dim)(BAD_ID, "abc", 8, &dimid);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* data mode test */
+    err = FileCreate(scratch, NC_CLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    err = APIFunc(def_dim)(ncid, "abc", 8, &dimid);
+    IF (err != NC_ENOTINDEFINE)
+        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* define-mode tests: unlimited dim */
+    err = APIFunc(redef)(ncid);
+    IF (err != NC_NOERR)
+        error("redef: %s", APIFunc(strerror)(err));
+    err = APIFunc(def_dim)(ncid, dim_name[0], NC_UNLIMITED, &dimid);
+    IF (err != NC_NOERR)
+        error("def_dim: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    IF (dimid != 0)
+        error("Unexpected dimid");
+    ELSE_NOK
+    err = APIFunc(inq_unlimdim)(ncid, &dimid);
+    IF (err != NC_NOERR)
+        error("inq_unlimdim: %s", APIFunc(strerror)(err));
+    IF (dimid != 0)
+        error("Unexpected recdim");
+    err = APIFunc(inq_dimlen)(ncid, dimid, &length);
+    IF (length != 0)
+        error("Unexpected length");
+    err = APIFunc(def_dim)(ncid, "abc", NC_UNLIMITED, &dimid);
+    IF (err != NC_EUNLIMIT)
+        error("expecting NC_EUNLIMIT but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* define-mode tests: remaining dims */
+    for (i = 1; i < NDIMS; i++) {
+        err = APIFunc(def_dim)(ncid, dim_name[i-1], dim_len[i], &dimid);
+        IF (err != NC_ENAMEINUSE)
+            error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(def_dim)(ncid, BAD_NAME, dim_len[i], &dimid);
+        IF (err != NC_EBADNAME)
+            error("expecting NC_EBADNAME but got %s", nc_err_code_name(err));
+        ELSE_NOK
+ifdef(`PNETCDF', ,`if(sizeof(long) > 4) /* Fix: dmh 11/4/2011: works only if sizeof(long) > 4 */')
+        {
+            err = APIFunc(def_dim)(ncid, dim_name[i], (IntType)(NC_UNLIMITED-1), &dimid);
+            IF (err != NC_EDIMSIZE)
+                error("expecting NC_EDIMSIZE but got %s", nc_err_code_name(err));
+            ELSE_NOK
+        }
+        err = APIFunc(def_dim)(ncid, dim_name[i], dim_len[i], &dimid);
+        IF (err != NC_NOERR)
+            error("def_dim: %s", APIFunc(strerror)(err));
+        ELSE_NOK
+        IF (dimid != i)
+            error("Unexpected dimid");
+    }
+
+    /* Following just to expand unlimited dim */
+    Def_Vars(ncid, numVars);
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    Put_Vars(ncid, numVars);
+
+    /* Check all dims */
+    check_dims(ncid);
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(rename_dim)
+ *    try with bad netCDF handle, check error
+ *    check that proper rename worked with APIFunc(inq_dim)
+ *    try renaming to existing dimension name, check error
+ *    try with bad dimension handle, check error
+ */
+int
+TestFunc(rename_dim)(void)
+{
+    int ncid;
+    int  err, nok=0;             /* status */
+    char name[NC_MAX_NAME];
+
+    /* BAD_ID test */
+    err = APIFunc(rename_dim)(BAD_ID, 0, "abc");
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* main tests */
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    def_dims(ncid);
+    err = APIFunc(rename_dim)(ncid, BAD_DIMID, "abc");
+    IF (err != NC_EBADDIM)
+        error("expecting NC_EBADDIM but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(rename_dim)(ncid, 2, "abc");
+    IF (err != NC_NOERR)
+        error("rename_dim: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    err = APIFunc(inq_dimname)(ncid, 2, name);
+    IF (strcmp(name, "abc") != 0)
+        error("Unexpected name: %s", name);
+    err = APIFunc(rename_dim)(ncid, 0, "abc");
+    IF (err != NC_ENAMEINUSE)
+        error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(def_var)
+ *    try with bad netCDF handle, check error
+ *    try with bad name, check error
+ *    scalar tests:
+ *      check that proper define worked with APIFunc(inq_var)
+ *      try redefining an existing variable, check error
+ *      try with bad datatype, check error
+ *      try with bad number of dimensions, check error
+ *      try in data mode, check error
+ *    check that returned id is one more than previous id
+ *    try with bad dimension ids, check error
+ */
+int
+TestFunc(def_var)(VarArgs)
+{
+    int  ncid;
+    int  varid;
+    int  err, nok=0;             /* status */
+    int  i;
+    int  ndims;
+    int  natts;
+    char name[NC_MAX_NAME];
+    int dimids[MAX_RANK];
+    nc_type datatype;
+
+    /* BAD_ID test */
+    err = APIFunc(def_var)(BAD_ID, "abc", NC_SHORT, 0, NULL, &varid);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* scalar tests */
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    err = APIFunc(def_var)(ncid, "abc", NC_SHORT, 0, NULL, &varid);
+    IF (err != NC_NOERR)
+        error("def_var: %s", APIFunc(strerror)(err));
+    ELSE_NOK
+    err = APIFunc(inq_var)(ncid, varid, name, &datatype, &ndims, dimids, &natts);
+    IF (err != NC_NOERR)
+        error("inq_var: %s", APIFunc(strerror)(err));
+    IF (strcmp(name, "abc") != 0)
+        error("Unexpected name: %s", name);
+    IF (datatype != NC_SHORT)
+        error("Unexpected datatype");
+    IF (ndims != 0)
+        error("Unexpected rank");
+    err = APIFunc(def_var)(ncid, BAD_NAME, NC_SHORT, 0, NULL, &varid);
+    IF (err != NC_EBADNAME)
+        error("expecting NC_EBADNAME but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(def_var)(ncid, "abc", NC_SHORT, 0, NULL, &varid);
+    IF (err != NC_ENAMEINUSE)
+        error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(def_var)(ncid, "ABC", BAD_TYPE, -1, dimids, &varid);
+    IF (err != NC_EBADTYPE)
+        error("expecting NC_EBADTYPE but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(def_var)(ncid, "ABC", NC_SHORT, -1, dimids, &varid);
+    IF (err != NC_EINVAL)
+        error("expecting NC_EINVAL but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    err = APIFunc(def_var)(ncid, "ABC", NC_SHORT, 0, dimids, &varid);
+    IF (err != NC_ENOTINDEFINE)
+        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+
+    /* general tests using global vars */
+    err = FileCreate(scratch, NC_CLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    def_dims(ncid);
+    for (i = 0; i < numVars; i++) {
+        err = APIFunc(def_var)(ncid, var_name[i], var_type[i], var_rank[i],
+            var_dimid[i], &varid);
+        IF (err != NC_NOERR)
+            error("def_var: %s", APIFunc(strerror)(err));
+        ELSE_NOK
+        IF (varid != i)
+            error("Unexpected varid");
+        ELSE_NOK
+    }
+
+    /* try bad dim ids */
+    dimids[0] = BAD_DIMID;
+    err = APIFunc(def_var)(ncid, "abc", NC_SHORT, 1, dimids, &varid);
+    IF (err != NC_EBADDIM)
+        error("expecting NC_EBADDIM but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test PutVar1
+ */
+int
+TestFunc(put_var1)(VarArgs)
+{
+    int i, err, ncid, nok=0;
+    IntType j, index[MAX_RANK];
+    double value[1];
+    double buf[1];                /* (void *) buffer */
+    ifdef(`PNETCDF', `MPI_Datatype datatype;')
+
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = PutVar1(BAD_ID, 0, NULL, NULL, 1, MPI_DATATYPE_NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutVar1(ncid, BAD_VARID, NULL, NULL, 1, MPI_DATATYPE_NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        value[0] = 5;  /* reset to a value within bounds */
+
+        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = PutVar1(ncid, i, NULL, value, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+')dnl
+
+        /* test NC_EINVALCOORDS */
+        for (j = 0; j < var_rank[i]; j++) index[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            index[j] = var_shape[i][j]; /* out of boundary check */
+            err = PutVar1(ncid, i, index, value, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            index[j] = 0;
+        }
+
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != 0) error("error in toMixedBase");
+            value[0] = hash(var_type[i], var_rank[i], index);
+            if (inRange(value[0], var_type[i])) {
+                err = dbl2nc(value[0], var_type[i], buf);
+                IF (err != NC_NOERR)
+                    error("error in dbl2nc var:%s type:%s",
+                          var_name[i],s_nc_type(var_type[i]));
+                err = PutVar1(ncid, i, index, buf, 1, datatype);
+                IF (err != NC_NOERR)
+                    EXPECT_ERR(NC_NOERR, err)
+                ELSE_NOK
+            }
+        }
+    }
+
+    Check_Vars(ncid, numVars);
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test PutVara
+ * Choose a random point dividing each dim into 2 parts
+ * Put 2^rank (nslabs) slabs so defined
+ * Redefine buffer for each put.
+ * At end check all variables using Check_Vars
+ */
+int
+TestFunc(put_vara)(VarArgs)
+{
+    int d, i, k, err, nslabs, ncid, nok=0;
+    IntType j, nels;
+    IntType start[MAX_RANK];
+    IntType edge[MAX_RANK];
+    IntType index[MAX_RANK];
+    IntType mid[MAX_RANK];
+    double buf[MAX_NELS];         /* (void *) buffer */
+    char *p;                      /* (void *) pointer */
+    double value;
+    ifdef(`PNETCDF', `MPI_Datatype datatype;')
+
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = PutVara(BAD_ID, 0, start, edge, buf, 1, MPI_DATATYPE_NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutVara(ncid, BAD_VARID, start, edge, buf, 1, MPI_DATATYPE_NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        buf[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = PutVara(BAD_ID, i, start, edge, buf, 1, MPI_DATATYPE_NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
+
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+        }
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = PutVara(ncid, i, NULL, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = PutVara(ncid, i, start, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
+        ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = PutVara(ncid, i, start, edge, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;
+            err = PutVara(ncid, i, start, edge, buf, 1, datatype);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDG, err)
+            ELSE_NOK
+            edge[j] = 1;
+        }
+        /* Check correct error returned when nothing to put, when edge[*]==0 */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = PutVara(ncid, i, start, edge, buf, 0, datatype);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = PutVara(ncid, i, start, edge, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        for (k = 0; k < nslabs; k++) {
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                nels *= edge[j];
+            }
+            p = (char *) buf;
+            for (j = 0; j < nels; j++) {
+                err = toMixedBase(j, var_rank[i], edge, index);
+                IF (err != 0) error("error in toMixedBase");
+                for (d = 0; d < var_rank[i]; d++)
+                    index[d] += start[d];
+                value = hash(var_type[i], var_rank[i], index);
+                if (!inRange(value, var_type[i]))
+                    value = 0;
+                err = dbl2nc(value, var_type[i], p);
+                IF (err != NC_NOERR)
+                    error("error in dbl2nc");
+                p += nctypelen(var_type[i]);
+            }
+            err = PutVara(ncid, i, start, edge, buf, nels, datatype);
+            IF (err != NC_NOERR)
+                error("%s", APIFunc(strerror)(err));
+            ELSE_NOK
+        }
+    }
+
+    Check_Vars(ncid, numVars);
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test PutVars
+ * Choose a random point dividing each dim into 2 parts
+ * Put 2^rank (nslabs) slabs so defined
+ * Choose random stride from 1 to edge
+ * Redefine buffer for each put.
+ * At end check all variables using Check_Vars
+ */
+int
+TestFunc(put_vars)(VarArgs)
+{
+    int ncid, d, i, k, err, nslabs, nok=0;
+    PTRDType nstarts;        /* number of different starts */
+    IntType j, m, nels;
+    IntType start[MAX_RANK];
+    IntType edge[MAX_RANK];
+    IntType index[MAX_RANK];
+    IntType index2[MAX_RANK];
+    IntType mid[MAX_RANK];
+    IntType count[MAX_RANK];
+    IntType sstride[MAX_RANK];
+    PTRDType stride[MAX_RANK];
+    double buf[MAX_NELS]; /* (void *) buffer */
+    char *p;              /* (void *) pointer */
+    double value;
+    ifdef(`PNETCDF', `MPI_Datatype datatype;')
+
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = PutVars(BAD_ID, 0, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutVars(ncid, BAD_VARID, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        buf[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = PutVars(BAD_ID, i, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
+
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = PutVars(ncid, i, NULL, NULL, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = PutVars(ncid, i, start, NULL, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
+        ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDG, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;  /* strided edge error check */
+            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
+        }
+        /* Check correct error returned even when nothing to put */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = PutVars(ncid, i, start, edge, stride, buf, 0, datatype);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                stride[j] = (PTRDType)sstride[j];
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != 0) error("error in toMixedBase");
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * (IntType)stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+ */
+                p = (char *) buf;
+                for (j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != 0) error("error in toMixedBase");
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * (IntType)stride[d];
+                    value = hash(var_type[i], var_rank[i], index2);
+                    if (!inRange(value, var_type[i]))
+                        value = 0;
+                    err = dbl2nc(value, var_type[i], p);
+                    IF (err != NC_NOERR)
+                        error("error in dbl2nc");
+                    p += nctypelen(var_type[i]);
+                }
+                err = PutVars(ncid, i, index, count, stride, buf, nels, datatype);
+                IF (err != NC_NOERR)
+                    EXPECT_ERR(NC_NOERR, err)
+                ELSE_NOK
+            }
+        }
+    }
+
+    Check_Vars(ncid, numVars);
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test PutVarm
+ * Choose a random point dividing each dim into 2 parts
+ * Put 2^rank (nslabs) slabs so defined
+ * Choose random stride from 1 to edge
+ * Buffer is bit image of whole external variable.
+ * So all puts for a variable put different elements of buffer
+ * At end check all variables using Check_Vars
+ */
+int
+TestFunc(put_varm)(VarArgs)
+{
+    int ncid, nok=0;
+    int i;
+    int k;
+    int err;
+    int nslabs;
+    IntType j, m;
+    PTRDType nstarts;        /* number of different starts */
+    IntType start[MAX_RANK];
+    IntType edge[MAX_RANK];
+    IntType index[MAX_RANK];
+    IntType mid[MAX_RANK];
+    IntType count[MAX_RANK];
+    IntType sstride[MAX_RANK];
+    PTRDType stride[MAX_RANK];
+    PTRDType imap[MAX_RANK];
+    PTRDType imap2[MAX_RANK];
+    ifdef(`PNETCDF', `IntType bufcount;')
+    double buf[MAX_NELS];       /* (void *) buffer */
+    char *p;                    /* (void *) pointer */
+    double value;
+    ifdef(`PNETCDF', `MPI_Datatype datatype;')
+
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    /* check if can detect a bad file ID */
+    err = PutVarm(NC_EBADID, 0, NULL, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
+    IF (err != NC_EBADID)
+        EXPECT_ERR(NC_EBADID, err)
+    ELSE_NOK
+
+    /* check if can detect a bad variable ID */
+    err = PutVarm(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
+    IF (err != NC_ENOTVAR)
+        EXPECT_ERR(NC_ENOTVAR, err)
+    ELSE_NOK
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        buf[0] = 5;  /* reset to a value within bounds */
+
+        /* check if can detect a bad file ID */
+        err = PutVarm(BAD_ID, i, NULL, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL);
+        IF (err != NC_EBADID)
+            EXPECT_ERR(NC_EBADID, err)
+        ELSE_NOK
+
+        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
+
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+            imap[j] = 1;
+        }
+
+ifdef(`PNETCDF',`dnl
+        /* for non-scalar variables, argument start cannot be NULL */
+        err = PutVarm(ncid, i, NULL, NULL, NULL, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) { /* scalar variable */
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EINVALCOORDS) {
+            EXPECT_ERR(NC_EINVALCOORDS, err)
+        }
+        ELSE_NOK
+
+        /* for non-scalar variables, argument count cannot be NULL */
+        err = PutVarm(ncid, i, start, NULL, NULL, NULL, buf, 1, datatype);
+        if (var_rank[i] == 0) {
+            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
+        }
+        else IF (err != NC_EEDGE) {
+            EXPECT_ERR(NC_EEDGE, err)
+        }
+        ELSE_NOK
+')dnl
+
+        /* first test when edge[*] > 0 */
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_EEDGE)
+                EXPECT_ERR(NC_EEDG, err)
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;  /* strided edge error check */
+            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_ESTRIDE)
+                EXPECT_ERR(NC_ESTRIDE, err)
+            ELSE_NOK
+            stride[j] = 1;
+        }
+        /* Check correct error returned even when nothing to put */
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
+
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] == 0) continue; /* skip record dim */
+            start[j] = var_shape[i][j];
+            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 0, datatype);
+#ifdef RELAX_COORD_BOUND
+            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
+                EXPECT_ERR(NC_NOERR, err)
+#else
+            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+#endif
+            ELSE_NOK
+            start[j] = var_shape[i][j]+1; /* out of boundary check */
+            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                EXPECT_ERR(NC_EINVALCOORDS, err)
+            ELSE_NOK
+            start[j] = 0;
+        }
+        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
+
+        if (var_rank[i] > 0) {
+            int jj = var_rank[i] - 1;
+            imap[jj] = nctypelen(var_type[i]); /*  netCDF considers imap in bytes */
+            imap[jj] = 1;                      /* PnetCDF considers imap in elements */
+            for (; jj > 0; jj--)
+                imap[jj-1] = imap[jj] * (PTRDType)var_shape[i][jj];
+        }
+        p = (char *) buf;
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != 0) error("error in toMixedBase");
+            value = hash(var_type[i], var_rank[i], index);
+            if (!inRange(value, var_type[i]))
+                value = 0;
+            err = dbl2nc(value, var_type[i], p);
+            IF (err != NC_NOERR)
+                error("error in dbl2nc");
+            p += nctypelen(var_type[i]);
+        }
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                stride[j] = (PTRDType)sstride[j];
+                imap2[j] = imap[j] * (PTRDType)sstride[j];
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                if (var_rank[i] == 0 && i%2 == 0) {
+                    err = PutVarm(ncid, i, NULL, NULL, NULL, NULL, buf, 1, datatype);
+                } else {
+                    err = toMixedBase(m, var_rank[i], sstride, index);
+                    IF (err != 0) error("error in toMixedBase");
+                    for (j = 0; j < var_rank[i]; j++) {
+                        count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j];
+                        index[j] += start[j];
+                    }
+                    /* Random choice of forward or backward */
+/* TODO
+                    if ( roll(2) ) {
+                        for (j = 0; j < var_rank[i]; j++) {
+                            index[j] += (count[j] - 1) * (IntType)stride[j];
+                            stride[j] = -stride[j];
+                        }
+                    }
+ */
+                    j = fromMixedBase(var_rank[i], index, var_shape[i]);
+                    p = (char *) buf + (int)j * nctypelen(var_type[i]);
+                    ifdef(`PNETCDF', `for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= count[j];')
+                    err = PutVarm(ncid, i, index, count, stride, imap2, p, bufcount, datatype);
+                }
+                IF (err != NC_NOERR)
+                    EXPECT_ERR(NC_NOERR, err)
+                ELSE_NOK
+            }
+        }
+    }
+
+    Check_Vars(ncid, numVars);
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(rename_var)
+ *    try with bad netCDF handle, check error
+ *    try with bad variable handle, check error
+ *    try renaming to existing variable name, check error
+ *    check that proper rename worked with APIFunc(inq_varid)
+ *    try in data mode, check error
+ */
+int
+TestFunc(rename_var)(VarArgs)
+{
+    int ncid;
+    int varid;
+    int err, nok=0;
+    int i;
+    char name[NC_MAX_NAME];
+
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    err = APIFunc(rename_var)(ncid, BAD_VARID, "newName");
+    IF (err != NC_ENOTVAR)
+        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+
+    /* Prefix "new_" to each name */
+    for (i = 0; i < numVars; i++) {
+        err = APIFunc(rename_var)(BAD_ID, i, "newName");
+        IF (err != NC_EBADID)
+            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(rename_var)(ncid, i, var_name[numVars-1]);
+        IF (err != NC_ENAMEINUSE)
+            error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        strcpy(name, "new_");
+        strcat(name, var_name[i]);
+        err = APIFunc(rename_var)(ncid, i, name);
+        IF (err != NC_NOERR)
+            error("rename_var: %s", APIFunc(strerror)(err));
+        ELSE_NOK
+        err = APIFunc(inq_varid)(ncid, name, &varid);
+        IF (err != NC_NOERR)
+            error("inq_varid: %s", APIFunc(strerror)(err));
+        IF (varid != i)
+            error("Unexpected varid");
+    }
+
+    /* Change to data mode */
+    /* Try making names even longer. Then restore original names */
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    for (i = 0; i < numVars; i++) {
+        strcpy(name, "even_longer_");
+        strcat(name, var_name[i]);
+        err = APIFunc(rename_var)(ncid, i, name);
+        IF (err != NC_ENOTINDEFINE)
+            error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = APIFunc(rename_var)(ncid, i, var_name[i]);
+        IF (err != NC_NOERR)
+            error("rename_var: %s", APIFunc(strerror)(err));
+        ELSE_NOK
+        err = APIFunc(inq_varid)(ncid, var_name[i], &varid);
+        IF (err != NC_NOERR)
+            error("inq_varid: %s", APIFunc(strerror)(err));
+        IF (varid != i)
+            error("Unexpected varid");
+    }
+
+    Put_Vars(ncid, numVars);
+    Check_Vars(ncid, numVars);
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+int
+TestFunc(put_att)(AttVarArgs)
+{
+    int ncid, nok=0;
+    int varid;
+    int i;
+    int j;
+    IntType k;
+    int err;
+    double buf[MAX_NELS];       /* (void *) buffer */
+    char *p;                    /* (void *) pointer */
+    char *name;                 /* of att */
+    nc_type datatype;           /* of att */
+    IntType length;             /* of att */
+    double value;
+
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        for (j = 0; j < NATTS(i); j++) {
+            name = ATT_NAME(i,j);
+            datatype = ATT_TYPE(i,j);
+            length = ATT_LEN(i,j);
+            err = APIFunc(put_att)(BAD_ID, varid, name, datatype, length, buf);
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(put_att)(ncid, varid, BAD_NAME, datatype, length, buf);
+            IF (err != NC_EBADNAME)
+                error("expecting NC_EBADNAME but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(put_att)(ncid, BAD_VARID, name, datatype, length, buf);
+            IF (err != NC_ENOTVAR)
+                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(put_att)(ncid, varid, name, BAD_TYPE, length, buf);
+            IF (err != NC_EBADTYPE)
+                error("expecting NC_EBADTYPE but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            p = (char *) buf;
+            for (k=0; k<length; k++) {
+                value = hash(datatype, -1, &k);
+                if (!inRange(value, datatype))
+                    value = 0;
+                err = dbl2nc(value, datatype, p);
+                IF (err != NC_NOERR)
+                    error("error in dbl2nc");
+                p += nctypelen(datatype);
+            }
+            err = APIFunc(put_att)(ncid, varid, name, datatype, length, buf);
+            IF (err != NC_NOERR)
+                error("%s", APIFunc(strerror)(err));
+            ELSE_NOK
+        }
+    }
+
+    Check_Atts(ncid, numGatts, numVars);
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(copy_att)
+ *    try with bad source or target netCDF handles, check error
+ *    try with bad source or target variable handle, check error
+ *    try with nonexisting attribute, check error
+ *    check that NC_GLOBAL variable for source or target works
+ *    check that new attribute put works with target in define mode
+ *    check that old attribute put works with target in data mode
+ *    check that changing type and length of an attribute work OK
+ *    try with same ncid for source and target, different variables
+ *    try with same ncid for source and target, same variable
+ */
+int
+TestFunc(copy_att)(AttVarArgs)
+{
+    int ncid_in;
+    int ncid_out;
+    int varid;
+    int err, nok=0;
+    int i;
+    int j=0;
+    char *name;                 /* of att */
+    nc_type datatype;           /* of att */
+    IntType length;             /* of att */
+    char  value;
+
+    err = FileOpen(testfile, NC_NOWRITE, &ncid_in);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid_out);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    def_dims(ncid_out);
+    Def_Vars(ncid_out, numVars);
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        for (j = 0; j < NATTS(i); j++) {
+            name = ATT_NAME(i,j);
+            err = APIFunc(copy_att)(ncid_in, BAD_VARID, name, ncid_out, varid);
+            IF (err != NC_ENOTVAR)
+                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(copy_att)(ncid_in, varid, name, ncid_out, BAD_VARID);
+            IF (err != NC_ENOTVAR)
+                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(copy_att)(BAD_ID, varid, name, ncid_out, varid);
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(copy_att)(ncid_in, varid, name, BAD_ID, varid);
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(copy_att)(ncid_in, varid, "noSuch", ncid_out, varid);
+            IF (err != NC_ENOTATT)
+                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(copy_att)(ncid_in, varid, name, ncid_out, varid);
+            IF (err != NC_NOERR)
+                error("copy_att: %s", APIFunc(strerror)(err));
+            ELSE_NOK
+            err = APIFunc(copy_att)(ncid_out, varid, name, ncid_out, varid);
+            IF (err != NC_NOERR)
+                error("source = target: %s", APIFunc(strerror)(err));
+            ELSE_NOK
+        }
+    }
+
+    err = APIFunc(close)(ncid_in);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    /* Close scratch. Reopen & check attributes */
+    err = APIFunc(close)(ncid_out);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileOpen(scratch, NC_WRITE, &ncid_out);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    Check_Atts(ncid_out, numGatts, numVars);
+
+   /*
+    * change to define mode
+    * define single char. global att. ':a' with value 'A'
+    * This will be used as source for following copies
+    */
+    err = APIFunc(redef)(ncid_out);
+    IF (err != NC_NOERR)
+        error("redef: %s", APIFunc(strerror)(err));
+    err = APIFunc(put_att_text)(ncid_out, NC_GLOBAL, "a", 1, "A");
+    IF (err != NC_NOERR)
+        error("put_att_text: %s", APIFunc(strerror)(err));
+
+   /*
+    * change to data mode
+    * Use scratch as both source & dest.
+    * try copy to existing att. change type & decrease length
+    * rename 1st existing att of each var (if any) 'a'
+    * if this att. exists them copy ':a' to it
+    */
+    err = APIFunc(enddef)(ncid_out);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    for (i = 0; i < numVars; i++) {
+        if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
+            err = APIFunc(rename_att)(ncid_out, i, att_name[i][0], "a");
+            IF (err != NC_NOERR)
+                error("rename_att: %s", APIFunc(strerror)(err));
+            err = APIFunc(copy_att)(ncid_out, NC_GLOBAL, "a", ncid_out, i);
+            IF (err != NC_NOERR)
+                error("copy_att: %s", APIFunc(strerror)(err));
+            ELSE_NOK
+        }
+    }
+    err = APIFunc(close)(ncid_out);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    /* Reopen & check */
+    err = FileOpen(scratch, NC_WRITE, &ncid_out);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    for (i = 0; i < numVars; i++) {
+        if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
+            err = APIFunc(inq_att)(ncid_out, i, "a", &datatype, &length);
+            IF (err != NC_NOERR)
+                error("inq_att: %s", APIFunc(strerror)(err));
+            IF (datatype != NC_CHAR)
+                error("Unexpected type");
+            IF (length != 1)
+                error("Unexpected length");
+            err = APIFunc(get_att_text)(ncid_out, i, "a", &value);
+            IF (err != NC_NOERR)
+                error("get_att_text: %s", APIFunc(strerror)(err));
+            IF (value != 'A')
+                error("Unexpected value");
+        }
+    }
+
+    err = APIFunc(close)(ncid_out);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(rename_att)
+ *    try with bad netCDF handle, check error
+ *    try with bad variable handle, check error
+ *    try with nonexisting att name, check error
+ *    try renaming to existing att name, check error
+ *    check that proper rename worked with APIFunc(inq_attid)
+ *    try in data mode, check error
+ */
+int
+TestFunc(rename_att)(AttVarArgs)
+{
+    int ncid;
+    int varid;
+    int err;
+    int i;
+    int j;
+    IntType  k;
+    int attnum;
+    char *attname;
+    char name[NC_MAX_NAME];
+    char oldname[NC_MAX_NAME];
+    char newname[NC_MAX_NAME];
+    int nok = 0;      /* count of valid comparisons */
+    nc_type datatype;
+    nc_type atttype;
+    IntType length;
+    IntType attlength;
+    char  text[MAX_NELS];
+    double value[MAX_NELS];
+    double expect;
+
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    err = APIFunc(rename_att)(ncid, BAD_VARID, "abc", "newName");
+    IF (err != NC_ENOTVAR)
+        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+    Put_Atts(ncid, numGatts, numVars);
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        for (j = 0; j < NATTS(i); j++) {
+            attname = ATT_NAME(i,j);
+            err = APIFunc(rename_att)(BAD_ID, varid, attname, "newName");
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(rename_att)(ncid, varid, "noSuch", "newName");
+            IF (err != NC_ENOTATT)
+                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            strcpy(newname, "new_");
+            strcat(newname, attname);
+            err = APIFunc(rename_att)(ncid, varid, attname, newname);
+            IF (err != NC_NOERR)
+                error("rename_att: %s", APIFunc(strerror)(err));
+            ELSE_NOK
+            err = APIFunc(inq_attid)(ncid, varid, newname, &attnum);
+            IF (err != NC_NOERR)
+                error("inq_attid: %s", APIFunc(strerror)(err));
+            IF (attnum != j)
+                error("Unexpected attnum");
+        }
+    }
+
+    /* Close. Reopen & check */
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileOpen(scratch, NC_WRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        for (j = 0; j < NATTS(i); j++) {
+            attname = ATT_NAME(i,j);
+            atttype = ATT_TYPE(i,j);
+            attlength = ATT_LEN(i,j);
+            strcpy(newname, "new_");
+            strcat(newname, attname);
+            err = APIFunc(inq_attname)(ncid, varid, j, name);
+            IF (err != NC_NOERR)
+                error("inq_attname: %s", APIFunc(strerror)(err));
+            IF (strcmp(name, newname) != 0)
+                error("inq_attname: unexpected name");
+            err = APIFunc(inq_att)(ncid, varid, name, &datatype, &length);
+            IF (err != NC_NOERR)
+                error("inq_att: %s", APIFunc(strerror)(err));
+            IF (datatype != atttype)
+                error("inq_att: unexpected type");
+            IF (length != attlength)
+                error("inq_att: unexpected length");
+            if (datatype == NC_CHAR) {
+                err = APIFunc(get_att_text)(ncid, varid, name, text);
+                IF (err != NC_NOERR)
+                    error("get_att_text: %s", APIFunc(strerror)(err));
+                for (k = 0; k < attlength; k++) {
+                    expect = hash(datatype, -1, &k);
+                    IF (text[k] != (char)expect)
+                        error("get_att_text: unexpected value");
+                }
+            } else {
+                err = APIFunc(get_att_double)(ncid, varid, name, value);
+                IF (err != NC_NOERR)
+                    error("get_att_double: %s", APIFunc(strerror)(err));
+                for (k = 0; k < attlength; k++) {
+                    expect = hash(datatype, -1, &k);
+                    if (inRange(expect, datatype)) {
+                        IF (!equal(value[k],expect,datatype,NCT_DOUBLE))
+                            error("get_att_double: unexpected value");
+                    }
+                }
+            }
+        }
+    }
+
+    /* Now in data mode */
+    /* Try making names even longer. Then restore original names */
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        for (j = 0; j < NATTS(i); j++) {
+            attname = ATT_NAME(i,j);
+            strcpy(oldname, "new_");
+            strcat(oldname, attname);
+            strcpy(newname, "even_longer_");
+            strcat(newname, attname);
+            err = APIFunc(rename_att)(ncid, varid, oldname, newname);
+            IF (err != NC_ENOTINDEFINE)
+                error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(rename_att)(ncid, varid, oldname, attname);
+            IF (err != NC_NOERR)
+                error("rename_att: %s", APIFunc(strerror)(err));
+            ELSE_NOK
+            err = APIFunc(inq_attid)(ncid, varid, attname, &attnum);
+            IF (err != NC_NOERR)
+                error("inq_attid: %s", APIFunc(strerror)(err));
+            IF (attnum != j)
+                error("Unexpected attnum");
+        }
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(del_att)
+ *    try with bad netCDF handle, check error
+ *    try with bad variable handle, check error
+ *    try with nonexisting att name, check error
+ *    check that proper delete worked using:
+ *      APIFunc(inq_attid), APIFunc(inq_natts), APIFunc(inq_varnatts)
+ */
+int
+TestFunc(del_att)(AttVarArgs)
+{
+    int ncid;
+    int err, nok=0;
+    int i;
+    int j;
+    int attnum;
+    int natts;
+    int numatts;
+    int varid;
+    char *name;                 /* of att */
+
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    err = APIFunc(del_att)(ncid, BAD_VARID, "abc");
+    IF (err != NC_ENOTVAR)
+        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
+    ELSE_NOK
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+    Put_Atts(ncid, numGatts, numVars);
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        numatts = NATTS(i);
+        for (j = 0; j < numatts; j++) {
+            name = ATT_NAME(i,j);
+            err = APIFunc(del_att)(BAD_ID, varid, name);
+            IF (err != NC_EBADID)
+                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(del_att)(ncid, varid, "noSuch");
+            IF (err != NC_ENOTATT)
+                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+            ELSE_NOK
+            err = APIFunc(del_att)(ncid, varid, name);
+            IF (err != NC_NOERR)
+                error("del_att: %s", APIFunc(strerror)(err));
+            ELSE_NOK
+            err = APIFunc(inq_attid)(ncid, varid, name, &attnum);
+            IF (err != NC_ENOTATT)
+                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
+            if (i < 0) {
+                err = APIFunc(inq_natts)(ncid, &natts);
+                IF (err != NC_NOERR)
+                    error("inq_natts: %s", APIFunc(strerror)(err));
+                IF (natts != numatts-j-1)
+                    error("natts: expected %d, got %d", numatts-j-1, natts);
+            }
+            err = APIFunc(inq_varnatts)(ncid, varid, &natts);
+            IF (err != NC_NOERR)
+                error("inq_natts: %s", APIFunc(strerror)(err));
+            IF (natts != numatts-j-1)
+                error("natts: expected %d, got %d", numatts-j-1, natts);
+        }
+    }
+
+    /* Close. Reopen & check no attributes left */
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileOpen(scratch, NC_WRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(inq_natts)(ncid, &natts);
+    IF (err != NC_NOERR)
+        error("inq_natts: %s", APIFunc(strerror)(err));
+    IF (natts != 0)
+        error("natts: expected %d, got %d", 0, natts);
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        err = APIFunc(inq_varnatts)(ncid, varid, &natts);
+        IF (err != NC_NOERR)
+            error("inq_natts: %s", APIFunc(strerror)(err));
+        IF (natts != 0)
+            error("natts: expected %d, got %d", 0, natts);
+    }
+
+    /* restore attributes. change to data mode. try to delete */
+    err = APIFunc(redef)(ncid);
+    IF (err != NC_NOERR)
+        error("redef: %s", APIFunc(strerror)(err));
+    Put_Atts(ncid, numGatts, numVars);
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        numatts = NATTS(i);
+        for (j = 0; j < numatts; j++) {
+            name = ATT_NAME(i,j);
+            err = APIFunc(del_att)(ncid, varid, name);
+            IF (err != NC_ENOTINDEFINE)
+                error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
+            ELSE_NOK
+        }
+    }
+
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test APIFunc(set_fill)
+ *    try with bad netCDF handle, check error
+ *    try in read-only mode, check error
+ *    try with bad new_fillmode, check error
+ *    try in data mode, check error
+ *    check that proper set to NC_FILL works for record & non-record variables
+ *    (note that it is not possible to test NC_NOFILL mode!)
+ *    close file & create again for test using attribute _FillValue
+ */
+int
+TestFunc(set_fill)(VarArgs)
+{
+    int ncid;
+    int varid;
+    int err;
+    int i;
+    IntType j;
+    int old_fillmode;
+    int nok = 0;      /* count of valid comparisons */
+    char text = 0;
+    double value = 0;
+    double fill;
+    IntType index[MAX_RANK];
+
+    /* bad ncid */
+    err = APIFunc(set_fill)(BAD_ID, NC_NOFILL, &old_fillmode);
+    IF (err != NC_EBADID)
+        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
+
+    /* try in read-only mode */
+    err = FileOpen(testfile, NC_NOWRITE, &ncid);
+    IF (err != NC_NOERR)
+        error("open: %s", APIFunc(strerror)(err));
+    err = APIFunc(set_fill)(ncid, NC_NOFILL, &old_fillmode);
+    IF (err != NC_EPERM)
+        error("expecting NC_EPERM but got %s", nc_err_code_name(err));
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+
+    /* create scratch */
+    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+
+    /* BAD_FILLMODE */
+    err = APIFunc(set_fill)(ncid, BAD_FILLMODE, &old_fillmode);
+    IF (err != NC_EINVAL)
+        error("expecting NC_EINVAL but got %s", nc_err_code_name(err));
+
+    /* proper calls */
+    err = APIFunc(set_fill)(ncid, NC_NOFILL, &old_fillmode);
+    IF (err != NC_NOERR)
+        error("set_fill: %s", APIFunc(strerror)(err));
+    IF (old_fillmode != NC_NOFILL)
+        error("Unexpected old fill mode: %d", old_fillmode);
+    err = APIFunc(set_fill)(ncid, NC_FILL, &old_fillmode);
+    IF (err != NC_NOERR)
+        error("set_fill: %s", APIFunc(strerror)(err));
+    IF (old_fillmode != NC_NOFILL)
+        error("Unexpected old fill mode: %d", old_fillmode);
+
+    /* define dims & vars */
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+
+    /* Change to data mode. Set fillmode again */
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    err = APIFunc(set_fill)(ncid, NC_FILL, &old_fillmode);
+ifdef(`PNETCDF',
+    `IF (err != NC_ENOTINDEFINE)
+        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));',
+    `IF (err)
+        error("nc_set_fill: %s", nc_strerror(err));
+    IF (old_fillmode != NC_FILL)
+        error("Unexpected old fill mode: %d", old_fillmode);')dnl
+
+    /* Write record number NRECS to force writing of preceding records */
+    /* Assumes variable cr is char vector with UNLIMITED dimension */
+    err = APIFunc(inq_varid)(ncid, "cr", &varid);
+    IF (err != NC_NOERR)
+        error("inq_varid: %s", APIFunc(strerror)(err));
+    index[0] = NRECS;
+
+ifdef(`PNETCDF', `
+    for (i=0; i<=index[0]; i++)
+        err = APIFunc(fill_var_rec)(ncid, varid, i);')dnl
+
+    err = PutVar1TYPE(text)(ncid, varid, index, &text);
+    IF (err != NC_NOERR)
+        error("put_var1_text_all: %s", APIFunc(strerror)(err));
+
+    /* get all variables & check all values equal default fill */
+    for (i = 0; i < numVars; i++) {
+        ifdef(`PNETCDF', `if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */')
+        switch (var_type[i]) {
+            case NC_CHAR:   fill = (double)NC_FILL_CHAR;   break;
+            case NC_BYTE:   fill = (double)NC_FILL_BYTE;   break;
+            case NC_SHORT:  fill = (double)NC_FILL_SHORT;  break;
+            case NC_INT:    fill = (double)NC_FILL_INT;    break;
+            case NC_FLOAT:  fill = (double)NC_FILL_FLOAT;  break;
+            case NC_DOUBLE: fill = (double)NC_FILL_DOUBLE; break;
+            case NC_UBYTE:  fill = (double)NC_FILL_UBYTE;  break;
+            case NC_USHORT: fill = (double)NC_FILL_USHORT; break;
+            case NC_UINT:   fill = (double)NC_FILL_UINT;   break;
+            case NC_INT64:  fill = (double)NC_FILL_INT64;  break;
+            case NC_UINT64: fill = (double)NC_FILL_UINT64; break;
+            default: assert(0);
+        }
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != 0) error("error in toMixedBase");
+            if (var_type[i] == NC_CHAR) {
+                err = GetVar1TYPE(text)(ncid, i, index, &text);
+                IF (err != NC_NOERR)
+                    error("get_var1_text_all failed: %s", APIFunc(strerror)(err));
+                value = text;
+            } else {
+                err = GetVar1TYPE(double)(ncid, i, index, &value);
+                IF (err != NC_NOERR)
+                    error("get_var1_double_all failed: %s", APIFunc(strerror)(err));
+            }
+            IF (value != fill && fabs((fill - value)/fill) > DBL_EPSILON)
+                error("\n\t\t%s Value expected: %-23.17e,\n\t\t          read: %-23.17e\n",
+                        var_name[i],fill, value);
+            ELSE_NOK
+        }
+    }
+
+    /* close scratch & create again for test using attribute _FillValue */
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileCreate(scratch, NC_CLOBBER, &ncid);
+    IF (err != NC_NOERR) {
+        error("create: %s", APIFunc(strerror)(err));
+        return nok;
+    }
+    def_dims(ncid);
+    Def_Vars(ncid, numVars);
+
+    /* set _FillValue = 42 for all vars */
+    fill = 42;
+    text = 42;
+    for (i = 0; i < numVars; i++) {
+        if (var_type[i] == NC_CHAR) {
+            err = APIFunc(put_att_text)(ncid, i, "_FillValue", 1, &text);
+            IF (err != NC_NOERR)
+                error("put_att_text: %s", APIFunc(strerror)(err));
+        } else {
+            err = APIFunc(put_att_double)(ncid, i, "_FillValue",var_type[i],1,&fill);
+            IF (err != NC_NOERR)
+                error("put_att_double: %s", APIFunc(strerror)(err));
+        }
+    }
+
+    /* data mode. write records */
+    err = APIFunc(enddef)(ncid);
+    IF (err != NC_NOERR)
+        error("enddef: %s", APIFunc(strerror)(err));
+    index[0] = NRECS;
+
+ifdef(`PNETCDF', `
+    for (i=0; i<=index[0]; i++)
+        err = APIFunc(fill_var_rec)(ncid, varid, i);')dnl
+
+    err = PutVar1TYPE(text)(ncid, varid, index, &text);
+    IF (err != NC_NOERR)
+        error("put_var1_text_all: %s", APIFunc(strerror)(err));
+
+    /* get all variables & check all values equal 42 */
+    for (i = 0; i < numVars; i++) {
+        if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != 0) error("error in toMixedBase");
+            if (var_type[i] == NC_CHAR) {
+                err = GetVar1TYPE(text)(ncid, i, index, &text);
+                IF (err != NC_NOERR)
+                    error("get_var1_text_all failed: %s", APIFunc(strerror)(err));
+                value = text;
+            } else {
+                err = GetVar1TYPE(double)(ncid, i, index, &value);
+                IF (err != NC_NOERR)
+                    error("get_var1_double_all failed: %s", APIFunc(strerror)(err));
+            }
+            IF (value != fill)
+                error(" %s Value expected: %g, read: %g\n", var_name[i],fill, value);
+            ELSE_NOK
+        }
+    }
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+
+    return nok;
+}
+
+
+/* This function gets the version of a netCDF file, 1 is for netCDF
+   classic, 2 for 64-bit offset format, (someday) 3 for HDF5 format,
+   5 for 64-bit data format (CDF-5).
+*/
+#define MAGIC_NUM_LEN 4
+static
+int
+APIFunc(get_file_version)(char *path, int *version)
+{
+   int fd;
+   ssize_t read_len;
+   char magic[MAGIC_NUM_LEN];
+
+   /* Need two valid pointers - check for NULL. */
+   if (!version || !path)
+      return NC_EINVAL;
+
+   /* Figure out if this is a netcdf or hdf5 file. */
+   fd = open(path, O_RDONLY, 0600);
+   if (fd == -1) return errno;
+
+   read_len = read(fd, magic, MAGIC_NUM_LEN);
+   if (read_len == -1) {
+       close(fd);
+       return errno;
+   }
+   if (read_len != MAGIC_NUM_LEN) {
+       printf("Error: reading NC magic string unexpected short read\n");
+       close(fd);
+       return 0;
+   }
+
+   if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0)
+   {
+      if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC ||
+          magic[MAGIC_NUM_LEN-1] == NC_FORMAT_64BIT_OFFSET ||
+          magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF5)
+         *version = magic[MAGIC_NUM_LEN-1];
+      else
+        return NC_ENOTNC;
+   }
+   /*   tomorrow, tomorrow, I love you tomorrow, you're always a day
+       away! */
+   /*if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
+      *version = 3;*/
+   return NC_NOERR;
+}
+
+/*
+ * Test APIFunc(set_default_format)
+ *    try with bad default format
+ *    try with NULL old_formatp
+ *    try in data mode, check error
+ *    check that proper set to NC_FILL works for record & non-record variables
+ *    (note that it is not possible to test NC_NOFILL mode!)
+ *    close file & create again for test using attribute _FillValue
+ */
+int
+TestFunc(set_default_format)(void)
+{
+    int ncid, nok=0;
+    int err;
+    int i;
+    int version=1;
+    int old_format;
+
+    /* bad format */
+    err = APIFunc(set_default_format)(BAD_DEFAULT_FORMAT, &old_format);
+    IF (err != NC_EINVAL)
+        error("expecting NC_EINVAL but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* NULL old_formatp */
+    err = APIFunc(set_default_format)(NC_FORMAT_64BIT_OFFSET, NULL);
+    IF (err != NC_NOERR)
+       error("null old_fortmatp: status = %d", err);
+    ELSE_NOK
+
+    /* Cycle through available formats. */
+    for(i=NC_FORMAT_CLASSIC; i<NC_FORMAT_64BIT_DATA; i++)
+    {
+       if (i == NC_FORMAT_NETCDF4 || i == NC_FORMAT_NETCDF4_CLASSIC)
+           continue; /* test classic formats only */
+       if ((err = APIFunc(set_default_format)(i, NULL)))
+           error("setting classic format: status = %d", err);
+       ELSE_NOK
+       err = FileCreate(scratch, NC_CLOBBER, &ncid);
+       if (err != NC_NOERR)
+           error("bad nc_create: status = %d", err);
+       err = APIFunc(put_att_text)(ncid, NC_GLOBAL, "testatt", sizeof("blah"), "blah");
+       if (err != NC_NOERR)
+           error("bad put_att: status = %d", err);
+       err = APIFunc(close)(ncid);
+       if (err != NC_NOERR)
+           error("bad close: status = %d", err);
+       err = APIFunc(get_file_version)(scratch, &version);
+       if (err != NC_NOERR)
+           error("bad file version = %d", err);
+       if (version != i) {
+          if (i == 4) {
+              if (version == 3) continue;
+              printf("expect version 3 but got %d (file=%s)",version,scratch);
+              continue;
+          }
+          printf("expect version %d but got %d (file=%s)",i,version,scratch);
+          error("bad file version = %d", version);
+        }
+    }
+
+    /* Remove the left-over file. */
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+
+    return nok;
+}
+
+
+
+
+/*
+ * Test FileDelete
+ *         create netcdf file 'scratch.nc' with no data, close it
+ *         delete the file
+ */
+int
+TestFunc(delete)(void)
+{
+    int err, nok=0;;
+    int ncid;
+
+    err = FileCreate(scratch, NC_CLOBBER, &ncid);
+    IF (err != NC_NOERR)
+        error("error creating scratch file %s, status = %d\n", scratch,err);
+    err = APIFunc(close)(ncid);
+    IF (err != NC_NOERR)
+        error("close: %s", APIFunc(strerror)(err));
+    err = FileDelete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    ELSE_NOK
+    return nok;
+}
diff --git a/test/nc_test/tests.h b/test/nc_test/tests.h
deleted file mode 100644
index ffcead3..0000000
--- a/test/nc_test/tests.h
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
- *  See COPYRIGHT notice in top-level directory.
- */
-/* $Id: tests.h 2293 2016-01-06 03:43:04Z wkliao $ */
-
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <limits.h>
-#include <float.h>
-#define NO_NETCDF_2 1
-#include <errno.h>
-#include <mpi.h>
-
-#include <pnetcdf.h>
-#include <testutils.h>
-#include "error.h"
-
-#include "ncconfig.h" /* output of 'configure' */
-
-#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
-
-/* Limits of external types (based on those in ncx.h) */
-
-/* Note: In CDF format specification, NC_CHAR is for text characters, which
- * is considered an 8-bit unsigned integer. Since it is for printable text
- * characters, its values should range from 0 (X_CHAR_MIN) to 255 (X_CHAR_MAX).
- */
-#define X_CHAR_MIN	0
-#define X_CHAR_MAX	255
-
-#define X_SCHAR_MIN     (-128)
-#define X_SCHAR_MAX     127
-#define X_UCHAR_MAX     255
-#define X_UCHAR_MIN     0
-#define X_BYTE_MIN	X_SCHAR_MIN
-#define X_BYTE_MAX	X_SCHAR_MAX
-#define X_SHORT_MIN	(-32768)
-#define X_SHORT_MAX	32767
-#define X_INT_MIN	(-2147483647-1)
-#define X_INT_MAX	2147483647
-#if defined(FLT_MAX_EXP) && FLT_MAX_EXP < 128
-/* FLT_MAX < X_FLOAT_MAX */
-#define X_FLOAT_MAX	FLT_MAX
-#else
-#define X_FLOAT_MAX	3.40282347e+38f
-#endif
-#define X_FLOAT_MIN	(-X_FLOAT_MAX)
-#if defined(CRAYFLOAT) && CRAYFLOAT != 0
-/* ldexp(1. - ldexp(.5 , -46), 1024) */
-#define X_DOUBLE_MAX    1.79769313486230e+308
-#else
-/* scalb(1. - scalb(.5 , -52), 1024) */
-#define X_DOUBLE_MAX	DBL_MAX
-#endif
-#define X_DOUBLE_MIN	-(DBL_MAX)
-
-#define X_UBYTE_MAX     X_UCHAR_MAX
-#define X_UBYTE_MIN     X_UCHAR_MIN
-#define X_USHORT_MAX    65535U
-#define X_USHORT_MIN    0
-#define X_UINT_MAX      4294967295U
-#define X_UINT_MIN      0
-
-#ifndef LLONG_MAX
-#define LLONG_MAX  0x7fffffffffffffffLL
-#endif
-#ifndef LLONG_MIN
-#define LLONG_MIN (-0x7fffffffffffffffLL-1)
-#endif
-#ifndef ULLONG_MAX
-#define ULLONG_MAX  0xffffffffffffffffULL
-#endif
-
-#ifndef X_INT64_MAX
-#define X_INT64_MAX    LLONG_MAX
-#endif
-#ifndef X_INT64_MIN
-#define X_INT64_MIN    LLONG_MIN
-#endif
-#ifndef X_UINT64_MAX
-#define X_UINT64_MAX  ULLONG_MAX
-#endif
-#ifndef X_UINT64_MIN
-#define X_UINT64_MIN  ULLONG_MIN
-#endif
-
-
-#if defined(_SX) && _SX != 0 /* 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 */
-
-
-#ifndef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif /* MAX */
-
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif /* MIN */
-
-#ifndef ABS
-#define ABS(x)  ((x) < 0 ? -(x) : (x))
-#endif /* ABS */
-
-    /* Parameters of test data */
-
-#define NTYPES      11   /* number of nc_types to test */
-#define NDIMS        5
-#define NRECS        2
-#define NGATTS       NTYPES
-#define RECDIM       0
-#define MAX_RANK     3
-#define MAX_NELS    64
-#define MAX_DIM_LEN  4
-#define MAX_NATTS    3
-/*
- *  #define NVARS 136   when NTYPES==6
- *  #define NVARS 142   when NTYPES==7
- *  #define NVARS 148   when NTYPES==8
- *  #define NVARS 154   when NTYPES==9
- *  #define NVARS 160   when NTYPES==10
- *  #define NVARS 166   when NTYPES==11
- *  c:char, b:byte, s:short, i:int, f:float, d:double, y:ubyte, t:ushort,
- *  u:uint, x:int64, z:uint64
- */
-#define NVARS 166
-
-/*
- *  * global variables (defined by command line processing in main())
- *   * related use of CDF-1 vs CDF-2 file formats
- *    */
-extern int cdf_format;  /* 1: CDF-1, 2: CDF-2 5: CDF-5 */
-extern int extra_flags; /* if using CDF-2 format, will be set to NC_64BIT_OFFSET
-                           if using CDF-5 format, will be set to NC_64BIT_DATA */
-extern int numGatts;  /* number of global attributes */
-extern int numVars;   /* number of variables */
-extern int numTypes;  /* number of netCDF data types to test */
-
-
-/* Here is how NVARS is acalculated in init_gvars().
-MAX_RANK=3
-MAX_DIM_LEN==4
-max_dim_len[MAX_RANK] = {MAX_DIM_LEN +1, MAX_DIM_LEN, MAX_DIM_LEN };
-rank==0, nvars=1      ntypes=NTYPES  (if rank < 2)
-rank==1, nvars=5      ntypes=NTYPES  (if rank < 2)
-rank==2, nvars=5*4    ntypes=1       (if rank >= 2)
-rank==3, nvars=5*4*4  ntypes=1       (if rank >= 2)
-nv=1* 6+5* 6+5*4+5*4*4= 6+30+20+80 = 136 (if NTYPES==6)
-nv=1* 7+5* 7+5*4+5*4*4= 7+35+20+80 = 142 (if NTYPES==7)
-nv=1* 8+5* 8+5*4+5*4*4= 8+40+20+80 = 148 (if NTYPES==8)
-nv=1* 9+5* 9+5*4+5*4*4= 9+45+20+80 = 154 (if NTYPES==9)
-nv=1*10+5*10+5*4+5*4*4=10+50+20+80 = 160 (if NTYPES==10)
-nv=1*11+5*11+5*4+5*4*4=11+55+20+80 = 166 (if NTYPES==11)
-*/
-
-/* Limits of internal types */
-
-/* Remove the use of text_min and text_max, becuase in NetCDF, there is no
- * situation that would cause to check the range of a text or NC_CHAR value.
- * In netCDF, a NC_CHAR variable must be read/written/created by netCDF text
- * APIs. Otherwise, NC_ECHAR error will return. In the text APIs, the user
- * buffers will be treated as a text array. For put APIs, a local signed char
- * value (if the local char is signed) will be type-casted to an unsigned char
- * value before writing to the file. For get APIs, an external unsigned char
- * (NC_CHAR) value will be type-casted to a local signed char value. If the
- * local char is unsigned, then no type casting will even happen. Also note
- * that netCDF text APIs never returns NC_ERANGE error code.
-
-#define text_min CHAR_MIN
-#define text_max CHAR_MAX
-*/
-
-#define uchar_min     0
-#define schar_min     SCHAR_MIN
-#define short_min     SHRT_MIN
-#define int_min       INT_MIN
-#define long_min      LONG_MIN
-#define float_min     (-FLT_MAX)
-#define double_min    (-DBL_MAX)
-#define ushort_min    0
-#define uint_min      0
-#define ulong_min     0
-#define int64_min     LLONG_MIN
-#define longlong_min  int64_min
-#define uint64_min    0
-#define ulonglong_min uint64_min
-
-#define uchar_max     UCHAR_MAX
-#define schar_max     SCHAR_MAX
-#define short_max     SHRT_MAX
-#define int_max       INT_MAX
-#define long_max      LONG_MAX
-#define float_max     FLT_MAX
-#define double_max    DBL_MAX
-#define ushort_max    USHRT_MAX
-#define uint_max      UINT_MAX
-#define ulong_max     ULONG_MAX
-#define int64_max     LLONG_MAX
-#define longlong_max  int64_max
-#define uint64_max    ULLONG_MAX
-#define ulonglong_max uint64_max
-
-
-
-    /* Examples of invalid argument values */
-
-#define BAD_ID -1               /* invalid netCDF ID */
-#define BAD_DIMID -1            /* invalid dim ID */
-#define BAD_VARID -2            /* invalid var ID */
-#define BAD_ATTNUM -1           /* invalid att number */
-#define BAD_TYPE (nc_type) 0    /* invalid data type */
-#define BAD_FILLMODE -1         /* invalid fill mode */
-#define BAD_NAME "a/b"		/* invalid name */
-#define BAD_DEFAULT_FORMAT 12	/* invalid default format */
-
-#define LEN_OF(array) ((sizeof array) / (sizeof array[0]))
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-    /* Non-standard internal types */
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-typedef char text;
-typedef signed char schar;
-#if !defined(HAVE_UCHAR) && !defined(__osf__) && !defined(_AIX)
-typedef unsigned char uchar;
-#endif
-
-#ifndef HAVE_USHORT
-typedef unsigned short int  ushort;
-#endif
-
-#ifndef HAVE_UINT
-typedef unsigned int  uint;
-#endif
-
-#ifndef HAVE_INT64
-typedef long long  int64;
-#endif
-
-#ifndef HAVE_UINT64
-typedef unsigned long long  uint64;
-#endif
-
-typedef long long longlong;
-typedef unsigned long long ulonglong;
-
-
-    /* Global variables - filenames */
-
-extern char testfile[128];		/* netCDF read-only test data */
-extern char scratch[128];		/* netCDF test file for writing */
-
-    /* Global variables - command-line arguments */
-
-extern int read_only;	/* if 1, don't try to change files */
-extern int verbose;	/* if 1, print details of tests */
-extern int nfails;	/* number of failures in specific test */
-extern int use_cdf2;	/* if 1, use CDF-2 format (offset >2GB ) */
-extern int extra_flags;	/* if using CDF-2, need extra flags for create*/
-extern int max_nmpt;	/* max number of messages per test */
-
-
-    /* Global variables - test data */
-
-extern char       dim_name[NDIMS][3];
-extern MPI_Offset dim_len[NDIMS];
-extern char       var_name[NVARS][2+MAX_RANK];
-extern nc_type    var_type[NVARS];
-extern size_t     var_rank[NVARS];
-extern int        var_dimid[NVARS][MAX_RANK];
-extern MPI_Offset var_shape[NVARS][MAX_RANK];
-extern size_t     var_nels[NVARS];
-extern size_t     var_natts[NVARS];
-extern char       att_name[NVARS][MAX_NATTS][2];
-extern char       gatt_name[NGATTS][3];
-extern nc_type    att_type[NVARS][NGATTS];
-extern nc_type    gatt_type[NGATTS];
-extern size_t     att_len[NVARS][MAX_NATTS];
-extern size_t     gatt_len[NGATTS];
-
-/* Global variables: MPI data */
-extern MPI_Comm comm;
-extern MPI_Info info;
-
-    /* Macros for accessing attribute test data */
-    /* varid is -1 for NC_GLOBAL so can do global atts in same loop */
-
-#define VARID(varid)      (varid < 0 ? NC_GLOBAL : varid)
-#define NATTS(varid)      (varid < 0 ? numGatts : var_natts[varid])
-#define ATT_NAME(varid,j) (varid < 0 ? gatt_name[j] : att_name[varid][j])
-#define ATT_TYPE(varid,j) (varid < 0 ? gatt_type[j] : att_type[varid][j])
-#define ATT_LEN(varid,j)  (varid < 0 ? gatt_len[j] : att_len[varid][j])
-
-extern const char *s_nc_type(nc_type);
-
-extern int test_ncmpi_strerror(void);
-extern int test_ncmpi_open(void);
-extern int test_ncmpi_close(void);
-extern int test_ncmpi_delete(void);
-
-extern int test_ncmpi_inq(void);
-extern int test_ncmpi_inq_natts(void);
-extern int test_ncmpi_inq_ndims(void);
-extern int test_ncmpi_inq_nvars(void);
-extern int test_ncmpi_inq_unlimdim(void);
-
-extern int test_ncmpi_inq_dimid(void);
-extern int test_ncmpi_inq_dim(void);
-extern int test_ncmpi_inq_dimlen(void);
-extern int test_ncmpi_inq_dimname(void);
-
-extern int test_ncmpi_inq_varid(void);
-extern int test_ncmpi_inq_vardimid(void);
-extern int test_ncmpi_inq_varname(void);
-extern int test_ncmpi_inq_varnatts(void);
-extern int test_ncmpi_inq_varndims(void);
-extern int test_ncmpi_inq_vartype(void);
-extern int test_ncmpi_inq_var(void);
-
-extern int test_ncmpi_get_var(void);
-extern int test_ncmpi_get_var_text(void);
-extern int test_ncmpi_get_var_schar(void);
-extern int test_ncmpi_get_var_uchar(void);
-extern int test_ncmpi_get_var_short(void);
-extern int test_ncmpi_get_var_int(void);
-extern int test_ncmpi_get_var_long(void);
-extern int test_ncmpi_get_var_float(void);
-extern int test_ncmpi_get_var_double(void);
-extern int test_ncmpi_get_var_ushort(void);
-extern int test_ncmpi_get_var_uint(void);
-extern int test_ncmpi_get_var_longlong(void);
-extern int test_ncmpi_get_var_ulonglong(void);
-
-extern int test_ncmpi_get_var1(void);
-extern int test_ncmpi_get_var1_text(void);
-extern int test_ncmpi_get_var1_schar(void);
-extern int test_ncmpi_get_var1_uchar(void);
-extern int test_ncmpi_get_var1_short(void);
-extern int test_ncmpi_get_var1_int(void);
-extern int test_ncmpi_get_var1_long(void);
-extern int test_ncmpi_get_var1_float(void);
-extern int test_ncmpi_get_var1_double(void);
-extern int test_ncmpi_get_var1_ushort(void);
-extern int test_ncmpi_get_var1_uint(void);
-extern int test_ncmpi_get_var1_longlong(void);
-extern int test_ncmpi_get_var1_ulonglong(void);
-
-extern int test_ncmpi_get_vara(void);
-extern int test_ncmpi_get_vara_text(void);
-extern int test_ncmpi_get_vara_schar(void);
-extern int test_ncmpi_get_vara_uchar(void);
-extern int test_ncmpi_get_vara_short(void);
-extern int test_ncmpi_get_vara_int(void);
-extern int test_ncmpi_get_vara_long(void);
-extern int test_ncmpi_get_vara_float(void);
-extern int test_ncmpi_get_vara_double(void);
-extern int test_ncmpi_get_vara_ushort(void);
-extern int test_ncmpi_get_vara_uint(void);
-extern int test_ncmpi_get_vara_longlong(void);
-extern int test_ncmpi_get_vara_ulonglong(void);
-
-extern int test_ncmpi_get_vars(void);
-extern int test_ncmpi_get_vars_text(void);
-extern int test_ncmpi_get_vars_schar(void);
-extern int test_ncmpi_get_vars_uchar(void);
-extern int test_ncmpi_get_vars_short(void);
-extern int test_ncmpi_get_vars_int(void);
-extern int test_ncmpi_get_vars_long(void);
-extern int test_ncmpi_get_vars_float(void);
-extern int test_ncmpi_get_vars_double(void);
-extern int test_ncmpi_get_vars_ushort(void);
-extern int test_ncmpi_get_vars_uint(void);
-extern int test_ncmpi_get_vars_longlong(void);
-extern int test_ncmpi_get_vars_ulonglong(void);
-
-extern int test_ncmpi_get_varm(void);
-extern int test_ncmpi_get_varm_text(void);
-extern int test_ncmpi_get_varm_schar(void);
-extern int test_ncmpi_get_varm_uchar(void);
-extern int test_ncmpi_get_varm_short(void);
-extern int test_ncmpi_get_varm_int(void);
-extern int test_ncmpi_get_varm_long(void);
-extern int test_ncmpi_get_varm_float(void);
-extern int test_ncmpi_get_varm_double(void);
-extern int test_ncmpi_get_varm_ushort(void);
-extern int test_ncmpi_get_varm_uint(void);
-extern int test_ncmpi_get_varm_longlong(void);
-extern int test_ncmpi_get_varm_ulonglong(void);
-
-extern int test_ncmpi_iget_var(void);
-extern int test_ncmpi_iget_var_text(void);
-extern int test_ncmpi_iget_var_schar(void);
-extern int test_ncmpi_iget_var_uchar(void);
-extern int test_ncmpi_iget_var_short(void);
-extern int test_ncmpi_iget_var_int(void);
-extern int test_ncmpi_iget_var_long(void);
-extern int test_ncmpi_iget_var_float(void);
-extern int test_ncmpi_iget_var_double(void);
-extern int test_ncmpi_iget_var_ushort(void);
-extern int test_ncmpi_iget_var_uint(void);
-extern int test_ncmpi_iget_var_longlong(void);
-extern int test_ncmpi_iget_var_ulonglong(void);
-
-extern int test_ncmpi_iget_var1(void);
-extern int test_ncmpi_iget_var1_text(void);
-extern int test_ncmpi_iget_var1_schar(void);
-extern int test_ncmpi_iget_var1_uchar(void);
-extern int test_ncmpi_iget_var1_short(void);
-extern int test_ncmpi_iget_var1_int(void);
-extern int test_ncmpi_iget_var1_long(void);
-extern int test_ncmpi_iget_var1_float(void);
-extern int test_ncmpi_iget_var1_double(void);
-extern int test_ncmpi_iget_var1_ushort(void);
-extern int test_ncmpi_iget_var1_uint(void);
-extern int test_ncmpi_iget_var1_longlong(void);
-extern int test_ncmpi_iget_var1_ulonglong(void);
-
-extern int test_ncmpi_iget_vara(void);
-extern int test_ncmpi_iget_vara_text(void);
-extern int test_ncmpi_iget_vara_schar(void);
-extern int test_ncmpi_iget_vara_uchar(void);
-extern int test_ncmpi_iget_vara_short(void);
-extern int test_ncmpi_iget_vara_int(void);
-extern int test_ncmpi_iget_vara_long(void);
-extern int test_ncmpi_iget_vara_float(void);
-extern int test_ncmpi_iget_vara_double(void);
-extern int test_ncmpi_iget_vara_ushort(void);
-extern int test_ncmpi_iget_vara_uint(void);
-extern int test_ncmpi_iget_vara_longlong(void);
-extern int test_ncmpi_iget_vara_ulonglong(void);
-
-extern int test_ncmpi_iget_vars(void);
-extern int test_ncmpi_iget_vars_text(void);
-extern int test_ncmpi_iget_vars_schar(void);
-extern int test_ncmpi_iget_vars_uchar(void);
-extern int test_ncmpi_iget_vars_short(void);
-extern int test_ncmpi_iget_vars_int(void);
-extern int test_ncmpi_iget_vars_long(void);
-extern int test_ncmpi_iget_vars_float(void);
-extern int test_ncmpi_iget_vars_double(void);
-extern int test_ncmpi_iget_vars_ushort(void);
-extern int test_ncmpi_iget_vars_uint(void);
-extern int test_ncmpi_iget_vars_longlong(void);
-extern int test_ncmpi_iget_vars_ulonglong(void);
-
-extern int test_ncmpi_iget_varm(void);
-extern int test_ncmpi_iget_varm_text(void);
-extern int test_ncmpi_iget_varm_schar(void);
-extern int test_ncmpi_iget_varm_uchar(void);
-extern int test_ncmpi_iget_varm_short(void);
-extern int test_ncmpi_iget_varm_int(void);
-extern int test_ncmpi_iget_varm_long(void);
-extern int test_ncmpi_iget_varm_float(void);
-extern int test_ncmpi_iget_varm_double(void);
-extern int test_ncmpi_iget_varm_ushort(void);
-extern int test_ncmpi_iget_varm_uint(void);
-extern int test_ncmpi_iget_varm_longlong(void);
-extern int test_ncmpi_iget_varm_ulonglong(void);
-
-extern int test_ncmpi_get_att(void);
-extern int test_ncmpi_get_att_text(void);
-extern int test_ncmpi_get_att_schar(void);
-extern int test_ncmpi_get_att_uchar(void);
-extern int test_ncmpi_get_att_short(void);
-extern int test_ncmpi_get_att_int(void);
-extern int test_ncmpi_get_att_long(void);
-extern int test_ncmpi_get_att_float(void);
-extern int test_ncmpi_get_att_double(void);
-extern int test_ncmpi_get_att_ushort(void);
-extern int test_ncmpi_get_att_uint(void);
-extern int test_ncmpi_get_att_longlong(void);
-extern int test_ncmpi_get_att_ulonglong(void);
-
-extern int test_ncmpi_put_var(void);
-extern int test_ncmpi_put_var_text(void);
-extern int test_ncmpi_put_var_schar(void);
-extern int test_ncmpi_put_var_uchar(void);
-extern int test_ncmpi_put_var_short(void);
-extern int test_ncmpi_put_var_int(void);
-extern int test_ncmpi_put_var_long(void);
-extern int test_ncmpi_put_var_float(void);
-extern int test_ncmpi_put_var_double(void);
-extern int test_ncmpi_put_var_ushort(void);
-extern int test_ncmpi_put_var_uint(void);
-extern int test_ncmpi_put_var_longlong(void);
-extern int test_ncmpi_put_var_ulonglong(void);
-
-extern int test_ncmpi_put_var1(void);
-extern int test_ncmpi_put_var1_text(void);
-extern int test_ncmpi_put_var1_schar(void);
-extern int test_ncmpi_put_var1_uchar(void);
-extern int test_ncmpi_put_var1_short(void);
-extern int test_ncmpi_put_var1_int(void);
-extern int test_ncmpi_put_var1_long(void);
-extern int test_ncmpi_put_var1_float(void);
-extern int test_ncmpi_put_var1_double(void);
-extern int test_ncmpi_put_var1_ushort(void);
-extern int test_ncmpi_put_var1_uint(void);
-extern int test_ncmpi_put_var1_longlong(void);
-extern int test_ncmpi_put_var1_ulonglong(void);
-
-extern int test_ncmpi_put_vara(void);
-extern int test_ncmpi_put_vara_text(void);
-extern int test_ncmpi_put_vara_schar(void);
-extern int test_ncmpi_put_vara_uchar(void);
-extern int test_ncmpi_put_vara_short(void);
-extern int test_ncmpi_put_vara_int(void);
-extern int test_ncmpi_put_vara_long(void);
-extern int test_ncmpi_put_vara_float(void);
-extern int test_ncmpi_put_vara_double(void);
-extern int test_ncmpi_put_vara_ushort(void);
-extern int test_ncmpi_put_vara_uint(void);
-extern int test_ncmpi_put_vara_longlong(void);
-extern int test_ncmpi_put_vara_ulonglong(void);
-
-extern int test_ncmpi_put_vars(void);
-extern int test_ncmpi_put_vars_text(void);
-extern int test_ncmpi_put_vars_schar(void);
-extern int test_ncmpi_put_vars_uchar(void);
-extern int test_ncmpi_put_vars_short(void);
-extern int test_ncmpi_put_vars_int(void);
-extern int test_ncmpi_put_vars_long(void);
-extern int test_ncmpi_put_vars_float(void);
-extern int test_ncmpi_put_vars_double(void);
-extern int test_ncmpi_put_vars_ushort(void);
-extern int test_ncmpi_put_vars_uint(void);
-extern int test_ncmpi_put_vars_longlong(void);
-extern int test_ncmpi_put_vars_ulonglong(void);
-
-extern int test_ncmpi_put_varm(void);
-extern int test_ncmpi_put_varm_text(void);
-extern int test_ncmpi_put_varm_schar(void);
-extern int test_ncmpi_put_varm_uchar(void);
-extern int test_ncmpi_put_varm_short(void);
-extern int test_ncmpi_put_varm_int(void);
-extern int test_ncmpi_put_varm_long(void);
-extern int test_ncmpi_put_varm_float(void);
-extern int test_ncmpi_put_varm_double(void);
-extern int test_ncmpi_put_varm_ushort(void);
-extern int test_ncmpi_put_varm_uint(void);
-extern int test_ncmpi_put_varm_longlong(void);
-extern int test_ncmpi_put_varm_ulonglong(void);
-
-extern int test_ncmpi_iput_var(void);
-extern int test_ncmpi_iput_var_text(void);
-extern int test_ncmpi_iput_var_schar(void);
-extern int test_ncmpi_iput_var_uchar(void);
-extern int test_ncmpi_iput_var_short(void);
-extern int test_ncmpi_iput_var_int(void);
-extern int test_ncmpi_iput_var_long(void);
-extern int test_ncmpi_iput_var_float(void);
-extern int test_ncmpi_iput_var_double(void);
-extern int test_ncmpi_iput_var_ushort(void);
-extern int test_ncmpi_iput_var_uint(void);
-extern int test_ncmpi_iput_var_longlong(void);
-extern int test_ncmpi_iput_var_ulonglong(void);
-
-extern int test_ncmpi_iput_var1(void);
-extern int test_ncmpi_iput_var1_text(void);
-extern int test_ncmpi_iput_var1_schar(void);
-extern int test_ncmpi_iput_var1_uchar(void);
-extern int test_ncmpi_iput_var1_short(void);
-extern int test_ncmpi_iput_var1_int(void);
-extern int test_ncmpi_iput_var1_long(void);
-extern int test_ncmpi_iput_var1_float(void);
-extern int test_ncmpi_iput_var1_double(void);
-extern int test_ncmpi_iput_var1_ushort(void);
-extern int test_ncmpi_iput_var1_uint(void);
-extern int test_ncmpi_iput_var1_longlong(void);
-extern int test_ncmpi_iput_var1_ulonglong(void);
-
-extern int test_ncmpi_iput_vara(void);
-extern int test_ncmpi_iput_vara_text(void);
-extern int test_ncmpi_iput_vara_schar(void);
-extern int test_ncmpi_iput_vara_uchar(void);
-extern int test_ncmpi_iput_vara_short(void);
-extern int test_ncmpi_iput_vara_int(void);
-extern int test_ncmpi_iput_vara_long(void);
-extern int test_ncmpi_iput_vara_float(void);
-extern int test_ncmpi_iput_vara_double(void);
-extern int test_ncmpi_iput_vara_ushort(void);
-extern int test_ncmpi_iput_vara_uint(void);
-extern int test_ncmpi_iput_vara_longlong(void);
-extern int test_ncmpi_iput_vara_ulonglong(void);
-
-extern int test_ncmpi_iput_vars(void);
-extern int test_ncmpi_iput_vars_text(void);
-extern int test_ncmpi_iput_vars_schar(void);
-extern int test_ncmpi_iput_vars_uchar(void);
-extern int test_ncmpi_iput_vars_short(void);
-extern int test_ncmpi_iput_vars_int(void);
-extern int test_ncmpi_iput_vars_long(void);
-extern int test_ncmpi_iput_vars_float(void);
-extern int test_ncmpi_iput_vars_double(void);
-extern int test_ncmpi_iput_vars_ushort(void);
-extern int test_ncmpi_iput_vars_uint(void);
-extern int test_ncmpi_iput_vars_longlong(void);
-extern int test_ncmpi_iput_vars_ulonglong(void);
-
-extern int test_ncmpi_iput_varm(void);
-extern int test_ncmpi_iput_varm_text(void);
-extern int test_ncmpi_iput_varm_schar(void);
-extern int test_ncmpi_iput_varm_uchar(void);
-extern int test_ncmpi_iput_varm_short(void);
-extern int test_ncmpi_iput_varm_int(void);
-extern int test_ncmpi_iput_varm_long(void);
-extern int test_ncmpi_iput_varm_float(void);
-extern int test_ncmpi_iput_varm_double(void);
-extern int test_ncmpi_iput_varm_ushort(void);
-extern int test_ncmpi_iput_varm_uint(void);
-extern int test_ncmpi_iput_varm_longlong(void);
-extern int test_ncmpi_iput_varm_ulonglong(void);
-
-extern int test_ncmpi_put_att(void);
-extern int test_ncmpi_put_att_text(void);
-extern int test_ncmpi_put_att_schar(void);
-extern int test_ncmpi_put_att_uchar(void);
-extern int test_ncmpi_put_att_short(void);
-extern int test_ncmpi_put_att_int(void);
-extern int test_ncmpi_put_att_long(void);
-extern int test_ncmpi_put_att_float(void);
-extern int test_ncmpi_put_att_double(void);
-extern int test_ncmpi_put_att_ushort(void);
-extern int test_ncmpi_put_att_uint(void);
-extern int test_ncmpi_put_att_longlong(void);
-extern int test_ncmpi_put_att_ulonglong(void);
-
-extern int test_ncmpi_create(void);
-extern int test_ncmpi_redef(void);
-extern int test_ncmpi_enddef(void);
-extern int test_ncmpi_sync(void);
-extern int test_ncmpi_abort(void);
-extern int test_ncmpi_def_dim(void);
-extern int test_ncmpi_rename_dim(void);
-extern int test_ncmpi_def_var(void);
-extern int test_ncmpi_rename_var(void);
-extern int test_ncmpi_copy_att(void);
-
-extern int test_ncmpi_inq_att(void);
-extern int test_ncmpi_inq_attname(void);
-extern int test_ncmpi_inq_attid(void);
-extern int test_ncmpi_inq_attlen(void);
-extern int test_ncmpi_inq_atttype(void);
-
-extern int test_ncmpi_rename_att(void);
-extern int test_ncmpi_del_att(void);
-extern int test_ncmpi_set_fill(void);
-extern int test_ncmpi_set_default_format(void);
-
-extern void print_nok(int nok);
-
-#define PRINT_NOK(nok) if (verbose) print("%4d good comparisons.\n",nok);
-
-
-/*
- * internal types
- */
-typedef enum {
-	NCT_UNSPECIFIED = 0,
-	NCT_UCHAR =	1,	/* unsigned char */
-	NCT_TEXT =	16,	/* char */
-#define NCT_CHAR NCT_TEXT
-	NCT_SCHAR =	17,	/* signed char */
-	NCT_SHORT =	18,	/* short */
-	NCT_INT =	20,	/* int */
-	NCT_LONG =	22,	/* long */
-	NCT_FLOAT =	36,	/* float */
-	NCT_DOUBLE =	40,	/* double */
-	NCT_USHORT =	41,
-	NCT_UINT =	42,
-	NCT_INT64 =	43,
-#define NCT_LONGLONG NCT_INT64
-	NCT_UINT64 =	44
-#define NCT_ULONGLONG NCT_UINT64
-} nct_itype;
-
-extern int
-inRange(const double value, const nc_type datatype);
-
-extern int
-inRange3(const double value, const nc_type datatype, const nct_itype itype);
-
-extern int
-equal(double x, double y, nc_type extType, nct_itype itype);
-
-extern int
-equal2(double x, double y, nc_type extType);
-
-extern int
-int_vec_eq(const int *v1, const int *v2, const int n);
-
-extern int
-roll(int n);
-
-extern int
-toMixedBase(
-    size_t number,           /* number to be converted to mixed base */
-    size_t length,
-    const MPI_Offset base[], /* dimensioned [length], base[0] ignored */
-    MPI_Offset result[]);    /* dimensioned [length] */
-
-extern size_t
-fromMixedBase(
-    size_t length,
-    MPI_Offset number[],     /* dimensioned [length] */
-    MPI_Offset base[]);      /* dimensioned [length], base[0] ignored */
-
-extern int
-nc2dbl ( const nc_type datatype, const void *p, double *result);
-
-extern int
-dbl2nc ( const double d, const nc_type datatype, void *p);
-
-extern double
-hash( const nc_type type, const int rank, const MPI_Offset *index );
-
-extern long long
-hashx_llong(const int rank, const MPI_Offset *index);
-
-extern double
-hash4(const nc_type type, const int rank, const MPI_Offset *index, const nct_itype itype);
-
-extern void
-init_gvars(void);
-
-extern void
-def_dims(int ncid);
-
-extern void
-def_vars(int ncid);
-
-extern void
-put_atts(int ncid);
-
-extern void
-put_vars(int ncid);
-
-extern void
-write_file(char *filename);
-
-extern void
-check_dims(int ncid);
-
-extern void
-check_vars(int ncid);
-
-extern void
-check_atts(int ncid);
-
-extern void
-check_file(char *filename);
-
-extern int
-nctypelen(nc_type type);
-
-extern MPI_Datatype
-nc_mpi_type(nc_type type);
-
-extern char*
-ncmpii_err_code_name(int err);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/test/nc_test/tests.h.m4 b/test/nc_test/tests.h.m4
new file mode 100644
index 0000000..75a1430
--- /dev/null
+++ b/test/nc_test/tests.h.m4
@@ -0,0 +1,523 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl This file is supposed to be the same as PnetCDF's test_put.m4
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: tests.h.m4 2610 2016-11-11 04:34:32Z wkliao $ */
+
+define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl
+define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_put_$1',`test_nc_put_$1')')dnl
+define(`APIFunc',` ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <limits.h>
+#include <float.h>
+#define NO_NETCDF_2 1
+#include <errno.h>
+#include <mpi.h>
+
+#include <pnetcdf.h>
+#include <testutils.h>
+#include "error.h"
+
+#include "ncconfig.h" /* output of 'configure' */
+
+#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
+
+/* Limits of external types (based on those in ncx.h) */
+
+/* Note: In CDF format specification, NC_CHAR is for text characters, which
+ * is considered an 8-bit unsigned integer. Since it is for printable text
+ * characters, its values should range from 0 (X_CHAR_MIN) to 255 (X_CHAR_MAX).
+ */
+#define X_CHAR_MIN	0
+#define X_CHAR_MAX	255
+
+#define X_SCHAR_MIN     (-128)
+#define X_SCHAR_MAX     127
+#define X_UCHAR_MAX     255
+#define X_UCHAR_MIN     0
+#define X_BYTE_MIN	X_SCHAR_MIN
+#define X_BYTE_MAX	X_SCHAR_MAX
+#define X_SHORT_MIN	(-32768)
+#define X_SHORT_MAX	32767
+#define X_INT_MIN	(-2147483647-1)
+#define X_INT_MAX	2147483647
+#if defined(FLT_MAX_EXP) && FLT_MAX_EXP < 128
+/* FLT_MAX < X_FLOAT_MAX */
+#define X_FLOAT_MAX	FLT_MAX
+#else
+#define X_FLOAT_MAX	3.40282347e+38f
+#endif
+#define X_FLOAT_MIN	(-X_FLOAT_MAX)
+#if defined(CRAYFLOAT) && CRAYFLOAT != 0
+/* ldexp(1. - ldexp(.5 , -46), 1024) */
+#define X_DOUBLE_MAX    1.79769313486230e+308
+#else
+/* scalb(1. - scalb(.5 , -52), 1024) */
+#define X_DOUBLE_MAX	DBL_MAX
+#endif
+#define X_DOUBLE_MIN	-(DBL_MAX)
+
+#define X_UBYTE_MAX     X_UCHAR_MAX
+#define X_UBYTE_MIN     X_UCHAR_MIN
+#define X_USHORT_MAX    65535U
+#define X_USHORT_MIN    0
+#define X_UINT_MAX      4294967295U
+#define X_UINT_MIN      0
+
+#ifndef LLONG_MAX
+#define LLONG_MAX  0x7fffffffffffffffLL
+#endif
+#ifndef LLONG_MIN
+#define LLONG_MIN (-0x7fffffffffffffffLL-1)
+#endif
+#ifndef ULLONG_MAX
+#define ULLONG_MAX  0xffffffffffffffffULL
+#endif
+
+#ifndef X_INT64_MAX
+#define X_INT64_MAX    LLONG_MAX
+#endif
+#ifndef X_INT64_MIN
+#define X_INT64_MIN    LLONG_MIN
+#endif
+#ifndef X_UINT64_MAX
+#define X_UINT64_MAX  ULLONG_MAX
+#endif
+#ifndef X_UINT64_MIN
+#define X_UINT64_MIN  ULLONG_MIN
+#endif
+
+
+#if defined(_SX) && _SX != 0 /* 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 */
+
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif /* MAX */
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+#ifndef ABS
+#define ABS(x)  ((x) < 0 ? -(x) : (x))
+#endif /* ABS */
+
+    /* Parameters of test data */
+
+#define NTYPES      11   /* number of nc_types to test */
+#define NDIMS        5
+#define NRECS        2
+#define NGATTS       NTYPES
+#define RECDIM       0
+#define MAX_RANK     3
+#define MAX_NELS    64
+#define MAX_DIM_LEN  4
+#define MAX_NATTS    3
+/*
+ *  #define NVARS 136   when NTYPES==6
+ *  #define NVARS 142   when NTYPES==7
+ *  #define NVARS 148   when NTYPES==8
+ *  #define NVARS 154   when NTYPES==9
+ *  #define NVARS 160   when NTYPES==10
+ *  #define NVARS 166   when NTYPES==11
+ *  c:char, b:byte, s:short, i:int, f:float, d:double, y:ubyte, t:ushort,
+ *  u:uint, x:int64, z:uint64
+ */
+#define NVARS 166
+
+/* Here is how NVARS is acalculated in init_gvars().
+MAX_RANK=3
+MAX_DIM_LEN==4
+max_dim_len[MAX_RANK] = {MAX_DIM_LEN +1, MAX_DIM_LEN, MAX_DIM_LEN };
+rank==0, nvars=1      ntypes=NTYPES  (if rank < 2)
+rank==1, nvars=5      ntypes=NTYPES  (if rank < 2)
+rank==2, nvars=5*4    ntypes=1       (if rank >= 2)
+rank==3, nvars=5*4*4  ntypes=1       (if rank >= 2)
+nv=1* 6+5* 6+5*4+5*4*4= 6+30+20+80 = 136 (if NTYPES==6)
+nv=1* 7+5* 7+5*4+5*4*4= 7+35+20+80 = 142 (if NTYPES==7)
+nv=1* 8+5* 8+5*4+5*4*4= 8+40+20+80 = 148 (if NTYPES==8)
+nv=1* 9+5* 9+5*4+5*4*4= 9+45+20+80 = 154 (if NTYPES==9)
+nv=1*10+5*10+5*4+5*4*4=10+50+20+80 = 160 (if NTYPES==10)
+nv=1*11+5*11+5*4+5*4*4=11+55+20+80 = 166 (if NTYPES==11)
+*/
+
+/* Limits of internal types */
+
+/* Remove the use of text_min and text_max, becuase in NetCDF, there is no
+ * situation that would cause to check the range of a text or NC_CHAR value.
+ * In netCDF, a NC_CHAR variable must be read/written/created by netCDF text
+ * APIs. Otherwise, NC_ECHAR error will return. In the text APIs, the user
+ * buffers will be treated as a text array. For put APIs, a local signed char
+ * value (if the local char is signed) will be type-casted to an unsigned char
+ * value before writing to the file. For get APIs, an external unsigned char
+ * (NC_CHAR) value will be type-casted to a local signed char value. If the
+ * local char is unsigned, then no type casting will even happen. Also note
+ * that netCDF text APIs never returns NC_ERANGE error code.
+
+#define text_min CHAR_MIN
+#define text_max CHAR_MAX
+*/
+
+#define uchar_min     0
+#define schar_min     SCHAR_MIN
+#define short_min     SHRT_MIN
+#define int_min       INT_MIN
+#define long_min      LONG_MIN
+#define float_min     (-FLT_MAX)
+#define double_min    (-DBL_MAX)
+#define ushort_min    0
+#define uint_min      0
+#define ulong_min     0
+#define int64_min     LLONG_MIN
+#define longlong_min  int64_min
+#define uint64_min    0
+#define ulonglong_min uint64_min
+
+#define uchar_max     UCHAR_MAX
+#define schar_max     SCHAR_MAX
+#define short_max     SHRT_MAX
+#define int_max       INT_MAX
+#define long_max      LONG_MAX
+#define float_max     FLT_MAX
+#define double_max    DBL_MAX
+#define ushort_max    USHRT_MAX
+#define uint_max      UINT_MAX
+#define ulong_max     ULONG_MAX
+#define int64_max     LLONG_MAX
+#define longlong_max  int64_max
+#define uint64_max    ULLONG_MAX
+#define ulonglong_max uint64_max
+
+
+
+    /* Examples of invalid argument values */
+
+#define BAD_ID -1               /* invalid netCDF ID */
+#define BAD_DIMID -1            /* invalid dim ID */
+#define BAD_VARID -2            /* invalid var ID */
+#define BAD_ATTNUM -1           /* invalid att number */
+#define BAD_TYPE (nc_type) 0    /* invalid data type */
+#define BAD_FILLMODE -1         /* invalid fill mode */
+#define BAD_NAME "a/b"		/* invalid name */
+#define BAD_DEFAULT_FORMAT 12	/* invalid default format */
+
+#define LEN_OF(array) ((sizeof array) / (sizeof array[0]))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+    /* Non-standard internal types */
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+typedef char text;
+typedef signed char schar;
+#if !defined(HAVE_UCHAR) && !defined(__osf__) && !defined(_AIX)
+typedef unsigned char uchar;
+#endif
+
+#ifndef HAVE_USHORT
+typedef unsigned short int  ushort;
+#endif
+
+#ifndef HAVE_UINT
+typedef unsigned int  uint;
+#endif
+
+#ifndef HAVE_INT64
+typedef long long  int64;
+#endif
+
+#ifndef HAVE_UINT64
+typedef unsigned long long  uint64;
+#endif
+
+typedef long long longlong;
+typedef unsigned long long ulonglong;
+
+
+    /* Global variables - filenames */
+
+extern char testfile[128];		/* netCDF read-only test data */
+extern char scratch[128];		/* netCDF test file for writing */
+
+    /* Global variables - command-line arguments */
+
+extern int read_only;	/* if 1, don't try to change files */
+extern int verbose;	/* if 1, print details of tests */
+extern int nfails;	/* number of failures in specific test */
+extern int use_cdf2;	/* if 1, use CDF-2 format (offset >2GB ) */
+extern int extra_flags;	/* if using CDF-2, need extra flags for create*/
+extern int max_nmpt;	/* max number of messages per test */
+
+
+    /* Global variables - test data */
+
+extern char       dim_name[NDIMS][3];
+extern IntType    dim_len[NDIMS];
+extern char       var_name[NVARS][2+MAX_RANK];
+extern nc_type    var_type[NVARS];
+extern int        var_rank[NVARS];
+extern int        var_dimid[NVARS][MAX_RANK];
+extern IntType    var_shape[NVARS][MAX_RANK];
+extern IntType    var_nels[NVARS];
+extern int        var_natts[NVARS];
+extern char       att_name[NVARS][MAX_NATTS][2];
+extern char       gatt_name[NGATTS][3];
+extern nc_type    att_type[NVARS][NGATTS];
+extern nc_type    gatt_type[NGATTS];
+extern IntType    att_len[NVARS][MAX_NATTS];
+extern IntType    gatt_len[NGATTS];
+
+/* Global variables: MPI data */
+extern MPI_Comm comm;
+extern MPI_Info info;
+
+/* Macros for accessing attribute test data */
+/* varid is -1 for NC_GLOBAL so can do global atts in same loop */
+
+#define VARID(varid)      (varid < 0 ? NC_GLOBAL : varid)
+#define NATTS(varid)      (varid < 0 ? numGatts : var_natts[varid])
+#define ATT_NAME(varid,j) (varid < 0 ? gatt_name[j] : att_name[varid][j])
+#define ATT_TYPE(varid,j) (varid < 0 ? gatt_type[j] : att_type[varid][j])
+#define ATT_LEN(varid,j)  (varid < 0 ? gatt_len[j] : att_len[varid][j])
+
+extern const char *s_nc_type(nc_type);
+
+extern int test_ncmpi_strerror(void);
+extern int test_ncmpi_open(void);
+extern int test_ncmpi_close(void);
+extern int test_ncmpi_delete(void);
+
+extern int test_ncmpi_inq(int numGatts, int numVars);
+extern int test_ncmpi_inq_natts(int numGatts);
+extern int test_ncmpi_inq_ndims(void);
+extern int test_ncmpi_inq_nvars(int numVars);
+extern int test_ncmpi_inq_unlimdim(void);
+
+extern int test_ncmpi_inq_dimid(void);
+extern int test_ncmpi_inq_dim(void);
+extern int test_ncmpi_inq_dimlen(void);
+extern int test_ncmpi_inq_dimname(void);
+
+extern int test_ncmpi_inq_varid(int numVars);
+extern int test_ncmpi_inq_vardimid(int numVars);
+extern int test_ncmpi_inq_varname(int numVars);
+extern int test_ncmpi_inq_varnatts(int numGatts, int numVars);
+extern int test_ncmpi_inq_varndims(int numVars);
+extern int test_ncmpi_inq_vartype(int numVars);
+extern int test_ncmpi_inq_var(int numVars);
+
+include(`foreach.m4')dnl
+include(`utils.m4')dnl
+dnl
+define(`GETPUTAPI',`extern int dnl
+ifdef(`PNETCDF',
+ifelse(`$3',`',`test_ncmpi_$1_var$2',`test_ncmpi_$1_var$2_$3'),
+ifelse(`$3',`',`test_nc_$1_var$2',`test_nc_$1_var$2_$3'dnl
+))`(int numVars);'')
+dnl
+foreach(`putget', (put, get, iput, iget),
+        `foreach(`kind', (, 1, a, s, m),
+        `foreach(`itype', (,ITYPE_LIST),
+        `GETPUTAPI(putget,kind,itype)'
+)')')
+dnl
+define(`ATTRAPI',`extern int dnl
+ifdef(`PNETCDF',
+ifelse(`$2',`',`test_ncmpi_$1_att',`test_ncmpi_$1_att_$2'),
+ifelse(`$2',`',`test_nc_$1_att',`test_nc_$1_att_$2'dnl
+))`(int numGatts, int numVars);'')
+dnl
+foreach(`putget', (put, get),
+        `foreach(`itype', (,ITYPE_LIST),
+        `ATTRAPI(putget,itype)'
+)')
+
+extern int test_ncmpi_create(void);
+extern int test_ncmpi_redef(int numGatts, int numVars);
+extern int test_ncmpi_enddef(int numGatts, int numVars);
+extern int test_ncmpi_sync(int numGatts, int numVars);
+extern int test_ncmpi_abort(int numGatts, int numVars);
+extern int test_ncmpi_def_dim(int numVars);
+extern int test_ncmpi_rename_dim(void);
+extern int test_ncmpi_def_var(int numVars);
+extern int test_ncmpi_rename_var(int numVars);
+extern int test_ncmpi_copy_att(int numGatts, int numVars);
+
+extern int test_ncmpi_inq_att(int numGatts, int numVars);
+extern int test_ncmpi_inq_attname(int numGatts, int numVars);
+extern int test_ncmpi_inq_attid(int numGatts, int numVars);
+extern int test_ncmpi_inq_attlen(int numGatts, int numVars);
+extern int test_ncmpi_inq_atttype(int numGatts, int numVars);
+
+extern int test_ncmpi_rename_att(int numGatts, int numVars);
+extern int test_ncmpi_del_att(int numGatts, int numVars);
+extern int test_ncmpi_set_fill(int numVars);
+extern int test_ncmpi_set_default_format(void);
+
+extern void print_nok(int nok);
+
+#define PRINT_NOK(nok) if (verbose) print("%4d good comparisons.\n",nok);
+
+
+/*
+ * internal types
+ */
+typedef enum {
+	NCT_UNSPECIFIED = 0,
+	NCT_UCHAR =	1,	/* unsigned char */
+	NCT_TEXT =	16,	/* char */
+#define NCT_CHAR NCT_TEXT
+	NCT_SCHAR =	17,	/* signed char */
+	NCT_SHORT =	18,	/* short */
+	NCT_INT =	20,	/* int */
+	NCT_LONG =	22,	/* long */
+	NCT_FLOAT =	36,	/* float */
+	NCT_DOUBLE =	40,	/* double */
+	NCT_USHORT =	41,
+	NCT_UINT =	42,
+	NCT_INT64 =	43,
+#define NCT_LONGLONG NCT_INT64
+	NCT_UINT64 =	44
+#define NCT_ULONGLONG NCT_UINT64
+} nct_itype;
+
+extern int
+inRange(const double value, const nc_type datatype);
+
+extern int
+inRange3(const int cdf_format, const double value, const nc_type datatype, const nct_itype itype);
+
+extern int
+equal(const double x, const double y, nc_type extType, nct_itype itype);
+
+extern int
+equal2(const double x, const double y, nc_type extType);
+
+extern int
+int_vec_eq(const int *v1, const int *v2, const int n);
+
+extern IntType
+roll(IntType n);
+
+extern int
+toMixedBase(IntType number, int length, const IntType *base, IntType *result);
+
+extern IntType
+fromMixedBase(int length, IntType *number, IntType *base);
+
+extern int
+nc2dbl(const nc_type datatype, const void *p, double *result);
+
+extern int
+dbl2nc(const double d, const nc_type datatype, void *p);
+
+extern double
+hash(const nc_type type, const int rank, const IntType *index );
+
+extern long long
+hashx_llong(const int rank, const IntType *index);
+
+extern double
+hash4(const int cdf_format, const nc_type type, const int rank, const IntType *index, const nct_itype itype);
+
+extern void
+init_gvars(int numGatts, int numTypes, int numVars);
+
+extern void
+def_dims(int ncid);
+
+extern void
+def_vars(int ncid, int numVars);
+
+extern void
+put_atts(int ncid, int numGatts, int numVars);
+
+extern void
+put_vars(int ncid, int numVars);
+
+extern void
+write_file(char *filename, int numGatts, int numVars);
+
+extern void
+check_dims(int ncid);
+
+extern int
+check_vars(int ncid, int numVars);
+
+extern void
+check_atts(int ncid, int numGatts, int numVars);
+
+extern void
+check_file(char *filename, int numGatts, int numVars);
+
+extern int
+nctypelen(nc_type type);
+
+extern MPI_Datatype
+nc_mpi_type(nc_type type);
+
+extern char*
+ncmpii_err_code_name(int err);
+
+extern int
+default_fill_value(int xtype, double *fillp);
+
+dnl
+define(`HASH',`extern $1 hash_$1(const int cdf_format, const nc_type type,
+       const int rank, const IntType *index, const nct_itype `itype');')dnl
+dnl
+foreach(`itype',(ITYPE_LIST),`HASH(itype)
+')dnl
+
+define(`CHECK_VARS',`extern int check_vars_$1(const char *filename, int numVars);')dnl
+dnl
+foreach(`itype',(ITYPE_LIST),`CHECK_VARS(itype)
+')dnl
+
+define(`CHECK_ATTS',`extern int check_atts_$1(int ncid, int numGatts, int numVars);')dnl
+dnl
+foreach(`itype',(ITYPE_LIST),`CHECK_ATTS(itype)
+')dnl
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/test/nc_test/tst_atts3.c b/test/nc_test/tst_atts3.c
index 1bf2ddc..b9367d6 100644
--- a/test/nc_test/tst_atts3.c
+++ b/test/nc_test/tst_atts3.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: tst_atts3.c 2219 2015-12-11 22:30:03Z wkliao $ */
+/* $Id: tst_atts3.c 2557 2016-10-15 22:21:06Z wkliao $ */
 
 /* This program is based on the test program tst_atts3.c of the netCDF package */
 
@@ -137,7 +137,7 @@ tst_atts3(char *filename, int cmode)
     signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
     unsigned char uchar_in[ATT_LEN];
     short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
-    int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
+    int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 127, 100000};
     float float_in[ATT_LEN], float_out[ATT_LEN] = {-0.5, 0.25, 0.125};
     double double_in[ATT_LEN], double_out[ATT_LEN] = {-0.25, .5, 0.125};
     long long longlong_in[ATT_LEN] = {-1LL, -1LL, -1LL};
@@ -343,7 +343,7 @@ tst_atts3(char *filename, int cmode)
       }
       if ((err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in)) != NC_ERANGE) ERR
       for (i = 0; i < ATT_LEN; i++) {
-	 if (i == 0 || i == 2) continue;
+	 if (i == 0 || i == 2) continue; /* int_out[0] and int_out[2] are out of schar range */
 	 if (schar_in[i] != (signed char) int_out[i]) ERRV
       }
       err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in); ERR
@@ -354,9 +354,11 @@ tst_atts3(char *filename, int cmode)
 	 if (schar_in[i] != (signed char) double_out[i]) ERRV
 
       /* Read all atts (except text) as uchar. */
-      err=ncmpi_get_att_uchar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, uchar_in); ERR
-      for (i = 0; i < ATT_LEN; i++)
+      if ((err=ncmpi_get_att_uchar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, uchar_in)) != NC_ERANGE) ERR
+      for (i = 0; i < ATT_LEN; i++) {
+	 if (i == 0) continue; /* skip schar_out[0]=NC_MIN_BYTE as it causes NC_ERANGE */
 	 if (uchar_in[i] != (unsigned char) schar_out[i]) ERRV
+      }
       if ((err=ncmpi_get_att_uchar(ncid, NC_GLOBAL, ATT_SHORT_NAME, uchar_in)) != NC_ERANGE) ERR
 /*
       for (i = 0; i < ATT_LEN; i++)
diff --git a/test/nc_test/tst_misc.c b/test/nc_test/tst_misc.c
index f978ccb..120bde6 100644
--- a/test/nc_test/tst_misc.c
+++ b/test/nc_test/tst_misc.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  */
-/* $Id: tst_misc.c 2133 2015-09-26 19:16:01Z wkliao $ */
+/* $Id: tst_misc.c 2476 2016-09-06 01:05:33Z wkliao $ */
 
 /* This program is based on the test program tst_misc.c of the netCDF package */
 
@@ -71,7 +71,8 @@ main(int argc, char **argv)
 	 openstat = ncmpi_open(MPI_COMM_SELF, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid);
 	 /* Some platforms (OSX, buddy) return stat = 2 (file not found)
 	    for index i == 2.  Not sure why, but this is a work around. */
-	 if(openstat != NC_ENOTNC && openstat != NC_ENOENT) {
+	 if(openstat != NC_ENOTNC && openstat != NC_ENOENT && openstat != NC_EFILE) {
+            /* older version of OpenMPI and MPICH may return MPI_ERR_IO instead of MPI_ERR_NO_SUCH_FILE */
             printf("Expecting error code %d or %d but got %d\n",NC_ENOTNC,NC_ENOENT,openstat);
             nerrs++;
          }
diff --git a/test/nc_test/util.c b/test/nc_test/util.c
index 620436f..1c21c88 100644
--- a/test/nc_test/util.c
+++ b/test/nc_test/util.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: util.c 2293 2016-01-06 03:43:04Z wkliao $
+ *  $Id: util.c 2610 2016-11-11 04:34:32Z wkliao $
  */
 
 #include <math.h> /* floor() */
@@ -21,9 +21,9 @@ print_nok(int nok)
 
 /* Is value within external type range? */
 int
-inRange(const double value, const nc_type datatype)
+inRange(const double value, const nc_type xtype)
 {
-    switch (datatype) {
+    switch (xtype) {
         case NC_CHAR:   return value >= X_CHAR_MIN   && value <= X_CHAR_MAX;
         case NC_BYTE:   return value >= X_BYTE_MIN   && value <= X_BYTE_MAX;
         case NC_SHORT:  return value >= X_SHORT_MIN  && value <= X_SHORT_MAX;
@@ -37,33 +37,35 @@ inRange(const double value, const nc_type datatype)
         case NC_UINT64: return value >= 0            && value <= X_UINT64_MAX;
         default:
             assert(0);
-	    return(0);
+            return(0);
     }
 }
 
 static int
-inRange_uchar(const double value, const nc_type datatype)
+inRange_uchar(const int     cdf_format,
+              const double  value,
+              const nc_type xtype)
 {
-    /* check value of type datatype if within uchar range */
+    /* check value of type xtype if within uchar range */
 
-    if (datatype == NC_BYTE) {
+    if (cdf_format < NC_FORMAT_CDF5 && xtype == NC_BYTE) {
         /* netCDF specification make a special case for type conversion between
-         * uchar and scahr: do not check for range error. See
-         * http://www.unidata.ucar.edu/software/netcdf/docs_rc/data_type.html#type_conversion
+         * uchar and NC_BYTE: do not check for range error. See
+         * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
          */
         return(value >= 0 && value <= 255);
-        /* this is to ensure value is within the range of uchar */
+        /* this is to ensure value is within the range of uchar internal type */
     }
     /* else */
-    return inRange(value, datatype);
+    return inRange(value, xtype);
 }
 
 static int
-inRange_float(const double value, const nc_type datatype)
+inRange_float(const double value, const nc_type xtype)
 {
     double min, max;
 
-    switch (datatype) {
+    switch (xtype) {
         case NC_CHAR:   min = X_CHAR_MIN;   max = X_CHAR_MAX;  break;
         case NC_BYTE:   min = X_BYTE_MIN;   max = X_BYTE_MAX;  break;
         case NC_SHORT:  min = X_SHORT_MIN;  max = X_SHORT_MAX; break;
@@ -91,14 +93,11 @@ inRange_float(const double value, const nc_type datatype)
         case NC_UINT:   min = 0;            max = X_UINT_MAX;   break;
         case NC_INT64:  min = X_INT64_MIN;  max = X_INT64_MAX;  break;
         case NC_UINT64: min = 0;            max = X_UINT64_MAX; break;
-        default:
-            min = 0.0;
-            max = 0.0;
-            assert(0);
+        default: assert(0);
     }
     if (!( value >= min && value <= max)) {
 #if 0    /* DEBUG */
-        if (datatype == NC_FLOAT) {
+        if (xtype == NC_FLOAT) {
             fprintf(stderr, "\n");
             fprintf(stderr, "min   % .17e\n", min);
             fprintf(stderr, "value % .17e\n", value);
@@ -110,7 +109,7 @@ inRange_float(const double value, const nc_type datatype)
 #if FLT_MANT_DIG != DBL_MANT_DIG
     /* else */
     {
-        const float fvalue = value;
+        const float fvalue = (float)value;
         return fvalue >= min && fvalue <= max;
     }
 #else
@@ -120,16 +119,17 @@ inRange_float(const double value, const nc_type datatype)
 
 /* wrapper for inRange to handle special NC_BYTE/uchar adjustment */
 /* this function checks whether "value" to be casted to type "itype" is
- * within the range of external "datatype".
+ * within the range of external "xtype".
  */
 int
-inRange3(const double    value, 
-         const nc_type   datatype,
+inRange3(const int       cdf_format,
+         const double    value, 
+         const nc_type   xtype,
          const nct_itype itype)
 {
     /* netCDF specification make a special case for type conversion between
-     * uchar and scahr: do not check for range error. See
-     * http://www.unidata.ucar.edu/software/netcdf/docs_rc/data_type.html#type_conversion
+     * uchar and NC_BYTE: do not check for range error. See
+     * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
      * The _uchar and _schar functions were introduced in netCDF-3 to eliminate
      * an ambiguity, and support both signed and unsigned byte data. In
      * netCDF-2, whether the external NC_BYTE type represented signed or
@@ -142,13 +142,13 @@ inRange3(const double    value,
      */
     switch (itype) {
         case NCT_UCHAR:
-            return inRange_uchar(value, datatype);
+            return inRange_uchar(cdf_format, value, xtype);
         case NCT_FLOAT:
-            return inRange_float(value, datatype);
+            return inRange_float(value, xtype);
         default:
             break;
     }
-    return inRange(value, datatype);
+    return inRange(value, xtype);
 }
 
 
@@ -157,51 +157,48 @@ inRange3(const double    value,
  *  Use tolerant comparison based on IEEE FLT_EPSILON or DBL_EPSILON.
  */
 int
-equal(double x, 
-      double y, 
-      nc_type      extType,     /* external data type */
+equal(const double x, 
+      const double y, 
+      nc_type      xtype,     /* external data type */
       nct_itype    itype)
 {
     const double flt_epsilon = 1.19209290E-07;
     const double dbl_epsilon = 2.2204460492503131E-16;
     double epsilon;
 
-    epsilon = extType == NC_FLOAT ||
+    epsilon = xtype == NC_FLOAT ||
               itype == NCT_FLOAT ? flt_epsilon : dbl_epsilon;
 
-    if (extType == NC_CHAR && itype == NCT_TEXT) {
+    if (xtype == NC_CHAR && itype == NCT_TEXT) {
         /* because in-memory data type char can be signed or unsigned,
          * type cast the value from external NC_CHAR before the comparison
          */
         char x2 = (char) x;
         char y2 = (char) y;
-        x = x2;
-        y = y2;
+        return ABS(x2-y2) <= epsilon * MAX( ABS(x2), ABS(y2));
     }
     return ABS(x-y) <= epsilon * MAX( ABS(x), ABS(y));
 }
 
-/* this function is for the APIs without itype, i.e. extType == itype */
+/* this function is for the APIs without itype, i.e. xtype == itype */
 int
-equal2(
-    double x,
-    double y,
-    nc_type extType)    /* external data type */
+equal2(const double x,
+       const double y,
+       nc_type xtype)    /* external data type */
 {
     const double flt_epsilon = 1.19209290E-07;
     const double dbl_epsilon = 2.2204460492503131E-16;
     double epsilon;
 
-    epsilon = extType == NC_FLOAT ? flt_epsilon : dbl_epsilon;
+    epsilon = xtype == NC_FLOAT ? flt_epsilon : dbl_epsilon;
 
-    if (extType == NC_CHAR) {
+    if (xtype == NC_CHAR) {
         /* because in-memory data type char can be signed or unsigned,
          * type cast the value from external NC_CHAR before the comparison
          */
         char x2 = (char) x;
         char y2 = (char) y;
-        x = x2;
-        y = y2;
+        return ABS(x2-y2) <= epsilon * MAX( ABS(x2), ABS(y2));
     }
 
     return ABS(x-y) <= epsilon * MAX( ABS(x), ABS(y));
@@ -222,9 +219,9 @@ int_vec_eq(const int *v1, const int *v2, const int n)
  *  Generate random integer from 0 to n-1
  *  Like throwing an n-sided dice marked 0, 1, 2, ..., n-1
  */
-int roll( int n )
+MPI_Offset roll( MPI_Offset n )
 {
-    int  r;
+    MPI_Offset r;
 
     do
     /*
@@ -234,7 +231,7 @@ int roll( int n )
      * We don't use RAND_MAX here because not all compilation
      * environments define it (e.g. gcc(1) under SunOS 4.1.4).
      */
-    r = ((rand() % 32768) / 32767.0) * (n - 1) + 0.5;
+    r = (MPI_Offset)(((rand() % 32768) / 32767.0) * (n - 1) + 0.5);
     while (r >= n);
 
     return r;
@@ -257,12 +254,12 @@ int roll( int n )
  *              because 37 = 2x(3x4) + 2x(4) + 5
  */
 int
-toMixedBase(size_t           number,   /* to be converted to mixed base */
-            size_t           length,
+toMixedBase(MPI_Offset       number,   /* to be converted to mixed base */
+            int              length,
             const MPI_Offset base[],   /* in:  [length], base[0] ignored */
             MPI_Offset       result[]) /* out: [length] */
 {
-    size_t i;
+    int i;
 
     if (length > 0) {
         for (i = length - 1; i > 0; i--) {
@@ -285,13 +282,13 @@ toMixedBase(size_t           number,   /* to be converted to mixed base */
  *
  *      Author: Harvey Davies, Unidata/UCAR, Boulder, Colorado
  */
-size_t
-fromMixedBase(size_t     length,
+MPI_Offset
+fromMixedBase(int        length,
               MPI_Offset number[],  /* [length] */
               MPI_Offset base[])    /* [length], base[0] ignored */
 {
-    size_t i;
-    size_t result = 0;
+    int i;
+    MPI_Offset result = 0;
 
     for (i = 1; i < length; i++) {
         result += number[i-1];
@@ -304,11 +301,11 @@ fromMixedBase(size_t     length,
 
 
 /* Convert any nc_type to double */
-int nc2dbl ( const nc_type datatype, const void *p, double *result)
+int nc2dbl ( const nc_type xtype, const void *p, double *result)
 {
     if ( ! p ) return 2;
     if ( ! result ) return 3;
-    switch (datatype) {
+    switch (xtype) {
         case NC_CHAR:   *result = *((signed char *)    p); break;
         case NC_BYTE:   *result = *((signed char *)    p); break;
         case NC_UBYTE:  *result = *((unsigned char *)  p); break;
@@ -337,12 +334,12 @@ int nc2dbl ( const nc_type datatype, const void *p, double *result)
 
 
 /* Convert double to any nc_type */
-int dbl2nc ( const double d, const nc_type datatype, void *p)
+int dbl2nc ( const double d, const nc_type xtype, void *p)
 {
     double r;   /* rounded value */
 
     if (p == NULL) return 1;
-    switch (datatype) {
+    switch (xtype) {
         case NC_CHAR:
             r = floor(0.5+d);
             /* d is obtained from hash() which may be set to X_CHAR_MIN (0)
@@ -353,65 +350,65 @@ int dbl2nc ( const double d, const nc_type datatype, void *p)
              */
             if ( r < X_CHAR_MIN || r > X_CHAR_MAX ) return 2;
 #if defined(__CHAR_UNSIGNED__) && __CHAR_UNSIGNED__ != 0
-            *((signed char*) p) = r;
+            *((signed char*) p) = (signed char)r;
 #else
-            *((char   *) p) = r;
+            *((char   *) p) = (char)r;
 #endif
             break;
         case NC_BYTE:
             r = floor(0.5+d);
             if ( r < schar_min  ||  r > schar_max )  return 2;
-            *((signed char *) p) = r;
+            *((signed char *) p) = (signed char)r;
             break;
         case NC_UBYTE:
             r = floor(0.5+d);
             if ( r < 0.0  ||  r > uchar_max )  return 2;
-            *((unsigned char *) p) = r;
+            *((unsigned char *) p) = (unsigned char)r;
             break;
         case NC_SHORT:
             r = floor(0.5+d);
             if ( r < short_min  ||  r > short_max )  return 2;
-            *((short *) p) = r;
+            *((short *) p) = (short)r;
             break;
         case NC_USHORT:
             r = floor(0.5+d);
             if ( r < 0.0  ||  r > ushort_max )  return 2;
-            *((unsigned short *) p) = r;
+            *((unsigned short *) p) = (unsigned short)r;
             break;
         case NC_INT:
             r = floor(0.5+d);
             if ( r < long_min  ||  r > long_max )  return 2;
 #if INT_MAX >= X_INT_MAX
-            *((int   *) p) = r;
+            *((int   *) p) = (int)r;
 #else
-            *((long   *) p) = r;
+            *((long   *) p) = (long)r;
 #endif
             break;
         case NC_UINT:
             r = floor(0.5+d);
             if ( r < 0.0  ||  r > uint_max )  return 2;
 #if UINT_MAX >= X_UINT_MAX
-            *((unsigned int  *) p) = r;
+            *((unsigned int  *) p) = (unsigned int)r;
 #else
-            *((unsigned long *) p) = r;
+            *((unsigned long *) p) = (unsigned long)r;
 #endif
             break;
         case NC_FLOAT:
             if ( fabs(d) > float_max )  return 2;
-            *((float  *) p) = d;
+            *((float  *) p) = (float)d;
             break;
         case NC_DOUBLE:
-            *((double *) p) = d;
+            *((double *) p) = (double)d;
             break;
         case NC_INT64:
             r = floor(0.5+d);
             if ( r < int64_min  ||  r > int64_max )  return 2;
-            *((long long *) p) = r;
+            *((long long *) p) = (long long)r;
             break;
         case NC_UINT64:
             r = floor(0.5+d);
             if ( r < 0.0  ||  r > uint64_max )  return 2;
-            *((unsigned long long *) p) = r;
+            *((unsigned long long *) p) = (unsigned long long)r;
             break;
         default:
             return 1;
@@ -424,7 +421,7 @@ int dbl2nc ( const double d, const nc_type datatype, void *p)
 
 /* Generate data values as function of type, rank (-1 for attribute), index */
 double
-hash( const nc_type type, const int rank, const MPI_Offset *index ) 
+hash( const nc_type xtype, const int rank, const MPI_Offset *index ) 
 {
     double base;
     double result = 0.0;
@@ -435,7 +432,7 @@ hash( const nc_type type, const int rank, const MPI_Offset *index )
     if (abs(rank) == 1 && index[0] <= 3) {
         switch (index[0]) {
             case 0:
-                switch (type) {  /* test if can get/put MIN value */
+                switch (xtype) {  /* test if can get/put MIN value */
                     case NC_CHAR:   return X_CHAR_MIN;
                     case NC_BYTE:   return X_BYTE_MIN;
                     case NC_SHORT:  return X_SHORT_MIN;
@@ -451,7 +448,7 @@ hash( const nc_type type, const int rank, const MPI_Offset *index )
                     default:  assert(0);
                 }
             case 1:
-                switch (type) {  /* test if can get/put MAX value */
+                switch (xtype) {  /* test if can get/put MAX value */
                     case NC_CHAR:   return X_CHAR_MAX;
                     case NC_BYTE:   return X_BYTE_MAX;
                     case NC_SHORT:  return X_SHORT_MAX;
@@ -468,7 +465,7 @@ hash( const nc_type type, const int rank, const MPI_Offset *index )
                     default:  assert(0);
                 }
             case 2:
-                switch (type) {  /* test if can detect out-of-boundary value */
+                switch (xtype) {  /* test if can detect out-of-boundary value */
                     case NC_CHAR:   return 'A';
                     case NC_BYTE:   return X_BYTE_MIN-1.0;
                     case NC_SHORT:  return X_SHORT_MIN-1.0;
@@ -483,7 +480,7 @@ hash( const nc_type type, const int rank, const MPI_Offset *index )
                     default:  assert(0);
                 }
             case 3:
-                switch (type) {  /* test if can detect out-of-boundary value */
+                switch (xtype) {  /* test if can detect out-of-boundary value */
                     case NC_CHAR:   return 'Z';
                     case NC_BYTE:   return X_BYTE_MAX  +1.0;
                     case NC_SHORT:  return X_SHORT_MAX +1.0;
@@ -500,7 +497,7 @@ hash( const nc_type type, const int rank, const MPI_Offset *index )
         }
     } else { /* for array with more than 4 elements, pick some random numbers */
         /* wkliao: what is "base" ? */
-        switch (type) {
+        switch (xtype) {
             case NC_CHAR:   base =  2;  break;
             case NC_BYTE:   base = -2;  break;
             case NC_SHORT:  base = -5;  break;
@@ -531,16 +528,34 @@ hash( const nc_type type, const int rank, const MPI_Offset *index )
 
 /* wrapper for hash to handle special NC_BYTE/uchar adjustment */
 double
-hash4(const nc_type     type, 
+hash4(const int         cdf_format,
+      const nc_type     xtype, 
       const int         rank, 
       const MPI_Offset *index, 
       const nct_itype   itype)
 {
     double result;
 
-    result = hash(type, rank, index);
-    if (itype == NCT_UCHAR && type == NC_BYTE && result >= -128 && result < 0)
+    result = hash(xtype, rank, index);
+
+    /* netCDF specification make a special case for type conversion between
+     * uchar and NC_BYTE: do not check for range error. See
+     * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
+     * The _uchar and _schar functions were introduced in netCDF-3 to eliminate
+     * an ambiguity, and support both signed and unsigned byte data. In
+     * netCDF-2, whether the external NC_BYTE type represented signed or
+     * unsigned values was left up to the user. In netcdf-3, we treat NC_BYTE
+     * as signed for the purposes of conversion to short, int, long, float, or
+     * double. (Of course, no conversion takes place when the internal type is
+     * signed char.) In the _uchar functions, we treat NC_BYTE as if it were
+     * unsigned. Thus, no NC_ERANGE error can occur converting between NC_BYTE
+     * and unsigned char.
+     */
+    if (cdf_format < NC_FORMAT_CDF5 && 
+        itype == NCT_UCHAR && xtype == NC_BYTE &&
+        result >= -128 && result < 0)
         result += 256;
+
     return result;
 }
 
@@ -581,7 +596,7 @@ init_dims(const char *digit)
 }
 
 static void
-init_gatts(const char *type_letter)
+init_gatts(const char *type_letter, int numGatts)
 {
     int attid;
     for (attid = 0; attid < numGatts; attid++) {
@@ -594,7 +609,7 @@ init_gatts(const char *type_letter)
 }
 
 static MPI_Offset
-product(size_t nn, const MPI_Offset *sp)
+product(int nn, const MPI_Offset *sp)
 {
     MPI_Offset result = 1;
     while (nn-- > 0)
@@ -609,7 +624,7 @@ product(size_t nn, const MPI_Offset *sp)
    att_name, gatt_name, att_type, gatt_type, att_len, gatt_len
  */
 void
-init_gvars (void)
+init_gvars(int numGatts, int numTypes, int numVars)
 {
     const MPI_Offset max_dim_len[MAX_RANK] = {MAX_DIM_LEN +1,
                                               MAX_DIM_LEN,
@@ -620,7 +635,7 @@ init_gvars (void)
      */
     const char digit[] = "r123456789";
 
-    size_t rank;
+    int rank;
     int vn;           /* var number */
     int xtype;        /* index of type */
     int an;           /* attribute number */
@@ -640,7 +655,7 @@ init_gvars (void)
          * == max_dim_len[0] * max_dim_len[1] * ... * max_dim_len[rank-1] */
         const size_t nvars = product(rank, max_dim_len);
 
-        int jj;
+        size_t jj;
         for (jj=0; jj<nvars; jj++) {
             /* number types of this shape */
             const int ntypes = rank < 2 ? numTypes : 1;
@@ -682,7 +697,7 @@ init_gvars (void)
             }
         }
     }
-    init_gatts(type_letter);
+    init_gatts(type_letter, numGatts);
 }
 
 
@@ -702,7 +717,7 @@ def_dims(int ncid)
 
 /* define vars defined by global variables */
 void                                                        
-def_vars(int ncid)
+def_vars(int ncid, int numVars)
 {
     int i, err, var_id;
 
@@ -716,7 +731,7 @@ def_vars(int ncid)
 
 /* put attributes defined by global variables */
 void                                                        
-put_atts(int ncid)
+put_atts(int ncid, int numGatts, int numVars)
 {
     int  i, j, allInRange, err;
     MPI_Offset  k;
@@ -745,10 +760,10 @@ put_atts(int ncid)
                         error("ncmpi_put_att_double: %s", ncmpi_strerror(err));
                 } else {
                     /* when ATT_LEN(i,j) >= 3, some values returned for 3rd,
-                     * 4th, ... will be specially made to cause NC_ERANG
+                     * 4th, ... will be specially made to cause NC_ERANGE
                      */
                     IF (err != NC_ERANGE)
-                        error("type-conversion range error: status = %d", err);
+                        error("expecting NC_ERANGE but got %s", nc_err_code_name(err));
                 }
             }
         }
@@ -757,7 +772,7 @@ put_atts(int ncid)
 
 /* put variables defined by global variables */
 void                                                        
-put_vars(int ncid)
+put_vars(int ncid, int numVars)
 {
     MPI_Offset start[MAX_RANK];
     MPI_Offset index[MAX_RANK];
@@ -773,7 +788,7 @@ put_vars(int ncid)
             if (var_name[i][0] == 'c') { /* var_type[i] is NC_CHAR */
                 text[j] = hash(var_type[i], var_rank[i], index);
             } else {
-                value[j]  = hash(var_type[i], var_rank[i], index);
+                value[j] = hash(var_type[i], var_rank[i], index);
                 allInRange = allInRange && inRange(value[j], var_type[i]);
             }
         }
@@ -782,13 +797,28 @@ put_vars(int ncid)
             IF (err != NC_NOERR)
                 error("ncmpi_put_vara_text_all: %s", ncmpi_strerror(err));
         } else {
+            /* Note netCDF below uses vara_double to write variables of all NC
+             * types. This will cause a problem for the special case when
+             * calling uchar APIs to access NC_BYTE variables in CDF-1 and 2
+             * files. For example, writing 128.0 double to NC_BYTE through
+             * vara_double API will get NC_ERANGE error, because NC_BYTE is
+             * considered a signed 1-byte integer by vara_double API. However,
+             * later on, when using vara_uchar APIs to read NC_BYTE, NC_ERANGE
+             * may not be expected, because NC_BYTE is considered unsigned by
+             * uchar APIs when file is in CDF-1 and 2 format.
+             */
             err = ncmpi_put_vara_double_all(ncid, i, start, var_shape[i],value);
             if (allInRange) {
                 IF (err != NC_NOERR)
                     error("ncmpi_put_vara_double_all: %s", ncmpi_strerror(err));
             } else {
+                /* In netCDF convention, even when NC_ERANGE is returned, the
+                 * out-of-bound data is still casted and written to the file.
+                 * See
+                 * http://www.unidata.ucar.edu/software/netcdf/docs/group__error.html
+                 */
                 IF (err != NC_ERANGE)
-                    error("type-conversion range error: status = %d", err);
+                    error("expecting NC_ERANGE but got %s", nc_err_code_name(err));
             }
         }
     }
@@ -797,22 +827,21 @@ put_vars(int ncid)
 
 /* Create & write all of specified file using global variables */
 void
-write_file(char *filename) 
+write_file(char *filename, int numGatts, int numVars) 
 {
     int  err, ncid;
 
-    err = ncmpi_create(comm, filename, NC_CLOBBER|extra_flags, info,
-                       &ncid);
+    err = ncmpi_create(comm, filename, NC_CLOBBER, info, &ncid);
     IF (err != NC_NOERR) error("ncmpi_create: %s", ncmpi_strerror(err));
 
     def_dims(ncid);
-    def_vars(ncid);
-    put_atts(ncid);
+    def_vars(ncid, numVars);
+    put_atts(ncid, numGatts, numVars);
 
     err = ncmpi_enddef(ncid);
     IF (err != NC_NOERR) error("ncmpi_enddef: %s", ncmpi_strerror(err));
 
-    put_vars(ncid);
+    put_vars(ncid, numVars);
 
     err = ncmpi_close (ncid);
     IF (err != NC_NOERR) error("ncmpi_close: %s", ncmpi_strerror(err));
@@ -834,9 +863,9 @@ check_dims(int  ncid)
         IF (err != NC_NOERR)
             error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
         IF (strcmp(name, dim_name[i]) != 0)
-            error("Unexpected name of dimension %d", i);
+            error("Unexpected name of dimension %d: '%s', expected: '%s'", i, name, dim_name[i]);
         IF (length != dim_len[i])
-            error("Unexpected length %d of dimension %d", length, i);
+            error("Unexpected length %d of dimension %d, expected %zu", length, i, dim_len[i]);
     }
 }
 
@@ -844,8 +873,8 @@ check_dims(int  ncid)
 /*
  * check variables of specified file have expected name, type, shape & values
  */
-void
-check_vars(int  ncid)
+int
+check_vars(int ncid, int numVars)
 {
     MPI_Offset index[MAX_RANK];
     char text, name[NC_MAX_NAME];
@@ -853,17 +882,17 @@ check_vars(int  ncid)
     int  nok = 0;      /* count of valid comparisons */
     int  isChar, ndims, dimids[MAX_RANK];
     double value, expect;
-    nc_type datatype;
+    nc_type xtype;
     MPI_Offset length;
 
     for (i = 0; i < numVars; i++) {
         isChar = var_type[i] == NC_CHAR;
-        err = ncmpi_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
+        err = ncmpi_inq_var(ncid, i, name, &xtype, &ndims, dimids, NULL);
         IF (err != NC_NOERR) 
             error("ncmpi_inq_var: %s", ncmpi_strerror(err));
         IF (strcmp(name, var_name[i]) != 0) 
             error("Unexpected var_name");
-        IF (datatype != var_type[i]) 
+        IF (xtype != var_type[i]) 
             error("Unexpected type");
         IF (ndims != var_rank[i]) 
             error("Unexpected rank");
@@ -880,10 +909,9 @@ check_vars(int  ncid)
                 error("error in toMixedBase 2");
             expect = hash( var_type[i], var_rank[i], index );
             if (isChar) {
-                ncmpi_begin_indep_data(ncid);
-                err = ncmpi_get_var1_text(ncid, i, index, &text);
+                err = ncmpi_get_var1_text_all(ncid, i, index, &text);
                 IF (err != NC_NOERR)
-                    error("ncmpi_get_var1_text: %s", ncmpi_strerror(err));
+                    error("ncmpi_get_var1_text_all: %s", ncmpi_strerror(err));
                 IF (text != (char)expect) {
                     error("Var %s (varid=%d) value read 0x%02x not that expected 0x%02x ",
                           var_name[i], i, text, (char)expect);
@@ -891,10 +919,8 @@ check_vars(int  ncid)
                 } else {
                     nok++;
                 }
-                ncmpi_end_indep_data(ncid);
             } else {
-                ncmpi_begin_indep_data(ncid);
-                err = ncmpi_get_var1_double(ncid, i, index, &value); 
+                err = ncmpi_get_var1_double_all(ncid, i, index, &value); 
                 if (inRange(expect,var_type[i])) {
                     IF (err != NC_NOERR) {
                         error("ncmpi_get_var1_double: %s", ncmpi_strerror(err));
@@ -908,11 +934,10 @@ check_vars(int  ncid)
                         }
                     }
                 }
-                ncmpi_end_indep_data(ncid);
             }
         }
     }
-    /* print_nok(nok); */
+    return nok;
 }
 
 
@@ -920,11 +945,11 @@ check_vars(int  ncid)
  * check attributes of specified file have expected name, type, length & values
  */
 void
-check_atts(int  ncid) 
+check_atts(int ncid, int numGatts, int numVars) 
 {
     char name[NC_MAX_NAME], text[MAX_NELS];
     int  i, j, err;        /* status */
-    nc_type datatype;
+    nc_type xtype;
     MPI_Offset k, length;
     double expect, value[MAX_NELS];
     int nok = 0;      /* count of valid comparisons */
@@ -936,19 +961,19 @@ check_atts(int  ncid)
                 error("ncmpi_inq_attname: %s", ncmpi_strerror(err));
             IF (strcmp(name, ATT_NAME(i,j)) != 0)
                 error("ncmpi_inq_attname: unexpected name");
-            err = ncmpi_inq_att(ncid, i, name, &datatype, &length);
+            err = ncmpi_inq_att(ncid, i, name, &xtype, &length);
             IF (err != NC_NOERR) 
                 error("ncmpi_inq_att: %s", ncmpi_strerror(err));
-            IF (datatype != ATT_TYPE(i,j))
+            IF (xtype != ATT_TYPE(i,j))
                 error("ncmpi_inq_att: unexpected type");
             IF (length != ATT_LEN(i,j))
                 error("ncmpi_inq_att: unexpected length");
-            if (datatype == NC_CHAR) {
+            if (xtype == NC_CHAR) {
                 err = ncmpi_get_att_text(ncid, i, name, text);
                 IF (err != NC_NOERR)
                     error("ncmpi_get_att_text: %s", ncmpi_strerror(err));
                 for (k = 0; k < ATT_LEN(i,j); k++) {
-                    expect = hash(datatype, -1, &k);
+                    expect = hash(xtype, -1, &k);
                     if (text[k] != (char)expect) {
                         error("ncmpi_get_att_text: unexpected value");
                     } else {
@@ -958,7 +983,7 @@ check_atts(int  ncid)
             } else {
                 err = ncmpi_get_att_double(ncid, i, name, value);
                 for (k = 0; k < ATT_LEN(i,j); k++) {
-                    expect = hash(datatype, -1, &k);
+                    expect = hash(xtype, -1, &k);
                     if (inRange(expect,ATT_TYPE(i,j))) {
                         IF (err != NC_NOERR)
                             error("ncmpi_get_att_double: %s", ncmpi_strerror(err));
@@ -978,7 +1003,7 @@ check_atts(int  ncid)
 
 /* Check file (dims, vars, atts) corresponds to global variables */
 void
-check_file(char *filename) 
+check_file(char *filename, int numGatts, int numVars)
 {
     int ncid, err;
 
@@ -987,8 +1012,8 @@ check_file(char *filename)
         error("ncmpi_open: %s", ncmpi_strerror(err));
     } else {
         check_dims(ncid);
-        check_vars(ncid);
-        check_atts(ncid);
+        check_vars(ncid, numVars);
+        check_atts(ncid, numGatts, numVars);
         err = ncmpi_close (ncid);
         IF (err != NC_NOERR) 
             error("ncmpi_close: %s", ncmpi_strerror(err));
@@ -997,9 +1022,9 @@ check_file(char *filename)
 
 /* TODO: Maybe this function belongs in the netcdf library. */
 const char *
-s_nc_type(nc_type type)
+s_nc_type(nc_type xtype)
 {
-    switch((int)type){
+    switch((int)xtype){
         case NC_CHAR:   return "NC_CHAR";
         case NC_BYTE:   return "NC_BYTE";
         case NC_UBYTE:  return "NC_UBYTE";
@@ -1016,9 +1041,9 @@ s_nc_type(nc_type type)
 }
 
 int
-nctypelen(nc_type type)
+nctypelen(nc_type xtype)
 {
-    switch(type){
+    switch(xtype){
         case NC_BYTE :
         case NC_CHAR :   return((int)sizeof(char));
         case NC_SHORT :  return((int)sizeof(short));
@@ -1035,9 +1060,9 @@ nctypelen(nc_type type)
 }
 
 MPI_Datatype
-nc_mpi_type(nc_type type)
+nc_mpi_type(nc_type xtype)
 {
-    switch(type){
+    switch(xtype){
         case NC_BYTE :   return MPI_SIGNED_CHAR;
         case NC_CHAR :   return MPI_CHAR;
         case NC_SHORT :  return MPI_SHORT;
@@ -1053,3 +1078,22 @@ nc_mpi_type(nc_type type)
     }
 }
 
+int
+default_fill_value(int xtype, double *fillp) {
+    switch(xtype) {
+        case NC_CHAR   : *fillp = (double)NC_FILL_CHAR;   break;
+        case NC_BYTE   : *fillp = (double)NC_FILL_BYTE;   break;
+        case NC_SHORT  : *fillp = (double)NC_FILL_SHORT;  break;
+        case NC_INT    : *fillp = (double)NC_FILL_INT;    break;
+        case NC_FLOAT  : *fillp = (double)NC_FILL_FLOAT;  break;
+        case NC_DOUBLE : *fillp = (double)NC_FILL_DOUBLE; break;
+        case NC_UBYTE  : *fillp = (double)NC_FILL_UBYTE;  break;
+        case NC_USHORT : *fillp = (double)NC_FILL_USHORT; break;
+        case NC_UINT   : *fillp = (double)NC_FILL_UINT;   break;
+        case NC_INT64  : *fillp = (double)NC_FILL_INT64;  break;
+        case NC_UINT64 : *fillp = (double)NC_FILL_UINT64; break;
+        default:         return NC_EBADTYPE;
+    }
+    return NC_NOERR;
+}
+
diff --git a/test/nf90_test/Makefile.in b/test/nf90_test/Makefile.in
index b534681..75a7eec 100644
--- a/test/nf90_test/Makefile.in
+++ b/test/nf90_test/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+# $Id: Makefile.in 2614 2016-11-12 19:50:02Z wkliao $
 #
 # @configure_input@
 
@@ -17,6 +17,10 @@ INCLUDES += @FC_MODINC at ../../src/libf90
 LDFLAGS  := $(LDFLAGS) -L../common
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
 
+ifeq (@RELAX_COORD_BOUND@, 1)
+FPPFLAGS := $(FPPFLAGS) @FC_DEFINE at RELAX_COORD_BOUND
+endif
+
 M4SRCS      = test_get.m4 \
               test_put.m4  \
               test_iget.m4 \
diff --git a/test/nf90_test/test_get.m4 b/test/nf90_test/test_get.m4
index 402cf80..fe45f39 100644
--- a/test/nf90_test/test_get.m4
+++ b/test/nf90_test/test_get.m4
@@ -1,11 +1,18 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
 dnl
-dnl  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
-dnl  See COPYRIGHT notice in top-level directory.
+dnl This file is supposed to be the same as PnetCDF's test_get.m4
 dnl
-dnl $Id: test_get.m4 1699 2014-07-05 00:32:53Z wkliao $
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
 dnl
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_get.m4 2619 2016-11-14 22:50:46Z wkliao $
 
-divert(-1)
+dnl divert(-1)
 
 dnl This is m4 source.
 dnl Process using m4 to produce FORTRAN language file.
@@ -121,8 +128,7 @@ define([TEST_NFMPI_GET_VAR1],[dnl
 
         nok = 0
 
-        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
-                         ncid)
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, ncid)
         if (err .ne. NF90_NOERR) &
             call errore('nf90mpi_open: ', err)
         err = nf90mpi_begin_indep_data(ncid)
@@ -151,8 +157,7 @@ define([TEST_NFMPI_GET_VAR1],[dnl
                 index(j) = 1
 3           continue
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
-                                    index)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), index)
                 if (err .ne. NF90_NOERR) &
                     call error('error in index2indexes 1')
                 expect = hash4( var_type(i), var_rank(i), index,  &
@@ -272,10 +277,8 @@ define([TEST_NFMPI_GET_VAR],[dnl
                         call errore('Range error: ', err)
                 endif
                 do 5, j = 1, var_nels(i)
-                    if (inRange3(expect(j),var_type(i), &
-                                 NFT_ITYPE($1)) .and. &
-                        in_internal_range(NFT_ITYPE($1), &
-                                                expect(j))) then
+                    if (inRange3(expect(j),var_type(i), NFT_ITYPE($1)) .and. &
+                        in_internal_range(NFT_ITYPE($1), expect(j))) then
                         val = ARITH3($1, value, j)
                         if (.not. equal(val, expect(j),  &
                                         var_type(i),  &
@@ -333,8 +336,7 @@ define([TEST_NFMPI_GET_VARA],[dnl
 
         nok = 0
 
-        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
-                         ncid)
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, ncid)
         if (err .ne. NF90_NOERR) &
             call errore('nf90mpi_open: ', err)
         do 1, i = 1, numVars
@@ -346,24 +348,20 @@ define([TEST_NFMPI_GET_VARA],[dnl
                 start(j) = 1
                 edge(j) = 1
 2           continue
-            err = nf90mpi_get_var_all(BAD_ID, i, value, start, &
-                        edge)
+            err = nf90mpi_get_var_all(BAD_ID, i, value, start, edge)
             if (err .ne. NF90_EBADID) &
                 call errore('bad ncid: ', err)
-            err = nf90mpi_get_var_all(ncid, BAD_VARID, value, start,  &
-                                 edge)
+            err = nf90mpi_get_var_all(ncid, BAD_VARID, value, start, edge)
             if (err .ne. NF90_ENOTVAR) &
                 call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
                 start(j) = var_shape(j,i) + 1
-                err = nf90mpi_get_var_all(ncid, i, value, start, &
-                                     edge)
+                err = nf90mpi_get_var_all(ncid, i, value, start, edge)
                 if (canConvert .and. err .ne. NF90_EINVALCOORDS) &
                     call errore('bad index: ', err)
                 start(j) = 1
                 edge(j) = var_shape(j,i) + 1
-                err = nf90mpi_get_var_all(ncid, i, value, start, &
-                                     edge)
+                err = nf90mpi_get_var_all(ncid, i, value, start, edge)
                 if (canConvert .and. err .ne. NF90_EEDGE) &
                     call errore('bad edge: ', err)
                 edge(j) = 1
@@ -372,29 +370,43 @@ define([TEST_NFMPI_GET_VARA],[dnl
 !           /* Check non-scalars for correct error returned even when */
 !           /* there is nothing to get (edge(j).eq.0) */
             if (var_rank(i) .gt. 0) then
-                do 10, j = 1, var_rank(i)
+                do 4, j = 1, var_rank(i)
                     edge(j) = 0
-10              continue
-                err = nf90mpi_get_var_all(BAD_ID, i, value, start, &
-                        edge)
+4               continue
+                err = nf90mpi_get_var_all(BAD_ID, i, value, start, edge)
                 if (err .ne. NF90_EBADID)  &
                     call errore('bad ncid: ', err)
-                err = nf90mpi_get_var_all(ncid, BAD_VARID, value, &
-                        start, edge)
+                err = nf90mpi_get_var_all(ncid, BAD_VARID, value, start, edge)
                 if (err .ne. NF90_ENOTVAR)  &
                     call errore('bad var id: ', err)
-                do 11, j = 1, var_rank(i)
-                    if (var_dimid(j,i) .gt. 1) then     !/* skip record dim */
-                        start(j) = var_shape(j,i) + 1
-                        err = nf90mpi_get_var_all(ncid, i, value, &
-                                start, edge)
-                        if (canConvert .and. err .ne. NF90_EINVALCOORDS) &
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_get_var_all(ncid, i, value, start, edge)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .ne. NF90_NOERR) &
+                            call error(nf90mpi_strerror(err))
+#else
+                        if (err .ne. NF90_EINVALCOORDS) &
                             call errore('bad start: ', err)
-                        start(j) = 1
+#endif
                     endif
-11              continue
-                err = nf90mpi_get_var_all(ncid, i, value, start, &
-                                edge)
+                    start(j) = var_shape(j,i) + 2
+                    err = nf90mpi_get_var_all(ncid, i, value, start, edge)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
+                err = nf90mpi_get_var_all(ncid, i, value, start, edge)
                 if (canConvert) then
                     if (err .ne. NF90_NOERR)  &
                         call error(nf90mpi_strerror(err))
@@ -402,22 +414,22 @@ define([TEST_NFMPI_GET_VARA],[dnl
                     if (err .ne. NF90_ECHAR) &
                         call errore('wrong type: ', err)
                 endif
-                do 12, j = 1, var_rank(i)
+                do 6, j = 1, var_rank(i)
                     edge(j) = 1
-12              continue
+6               continue
             endif
 
 !           Choose a random point dividing each dim into 2 parts
 !           get 2^rank (nslabs) slabs so defined
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
 !           bits of k determine whether to get lower or upper part of dim 
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nels = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift((k-1), -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -426,35 +438,31 @@ define([TEST_NFMPI_GET_VARA],[dnl
                         edge(j) = var_shape(j,i) - mid(j)
                     end if
                     nels = nels * edge(j)
-6               continue
+9               continue
                 allInIntRange = .true.
                 allInExtRange = .true.
-                do 7, j = 1, INT(nels)
+                do 10, j = 1, INT(nels)
                     err = index2indexes(j, var_rank(i), edge, index)
                     if (err .ne. NF90_NOERR) &
                         call error('error in index2indexes 1')
-                    do 8, d = 1, var_rank(i)
+                    do 11, d = 1, var_rank(i)
                         index(d) = index(d) + start(d) - 1
-8                   continue
+11                  continue
                     expect(j) = hash4(var_type(i), var_rank(i), index,  &
                                       NFT_ITYPE($1))
-                    if (inRange3(expect(j),var_type(i),  &
-                                 NFT_ITYPE($1))) then
-                        allInIntRange =  &
-                            allInIntRange .and. &
+                    if (inRange3(expect(j),var_type(i), NFT_ITYPE($1))) then
+                        allInIntRange = allInIntRange .and. &
                             in_internal_range(NFT_ITYPE($1), expect(j))
                     else
                         allInExtRange = .false.
                     end if
-7               continue
-                err = nf90mpi_get_var_all(ncid, i, value, start, &
-                                edge)
+10              continue
+                err = nf90mpi_get_var_all(ncid, i, value, start, edge)
                 if (canConvert) then
                     if (allInExtRange) then
                         if (allInIntRange) then
                             if (err .ne. NF90_NOERR) &
-                                call errore('nf90mpi_get_var:', &
-                                             err)
+                                call errore('nf90mpi_get_var:', err)
                         else
                             if (err .ne. NF90_ERANGE) &
                                 call errore('Range error: ', err)
@@ -463,24 +471,18 @@ define([TEST_NFMPI_GET_VARA],[dnl
                         if (err .ne. NF90_NOERR .and. err .ne. NF90_ERANGE) &
                             call errore('OK or Range error: ', err)
                     end if
-                    do 9, j = 1, INT(nels)
-                        if (inRange3(expect(j),var_type(i), &
-                                     NFT_ITYPE($1)) .and. &
-                            in_internal_range(NFT_ITYPE($1), expect(j))) &
-                                then
+                    do 12, j = 1, INT(nels)
+                        if (inRange3(expect(j),var_type(i), NFT_ITYPE($1)) .and. &
+                            in_internal_range(NFT_ITYPE($1), expect(j))) then
                             val = ARITH3($1, value, j)
                             if (.not.equal(val,expect(j), &
-                                           var_type(i),NFT_ITYPE($1)))  &
-                                    then
-                                call error( &
-                                    'value read not that expected')
+                                           var_type(i),NFT_ITYPE($1))) then
+                                call error('value read not that expected')
                                 if (verbose) then
                                     call error(' ')
                                     call errori('varid: ', i)
-                                    call errorc('var_name: ', &
-                                        var_name(i))
-                                    call errori('element number: %d ',  &
-                                                j)
+                                    call errorc('var_name: ', var_name(i))
+                                    call errori('element number: %d ', j)
                                     call errord('expect: ', expect(j))
                                     call errord('got: ', val)
                                 end if
@@ -488,12 +490,12 @@ define([TEST_NFMPI_GET_VARA],[dnl
                                 nok = nok + 1
                             end if
                         end if
-9                   continue
+12                  continue
                 else
                     if (nels .gt. 0  .and. err .ne. NF90_ECHAR) &
                         call errore('wrong type: ', err)
                 end if
-5           continue
+8           continue
 1       continue
         err = nf90mpi_close(ncid)
         if (err .ne. NF90_NOERR) &
@@ -544,8 +546,7 @@ define([TEST_NFMPI_GET_VARS],dnl
 
         nok = 0
 
-        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
-                         ncid)
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, ncid)
         if (err .ne. NF90_NOERR) &
             call errore('nf90mpi_open: ', err)
         do 1, i = 1, numVars
@@ -558,18 +559,15 @@ define([TEST_NFMPI_GET_VARS],dnl
                 edge(j) = 1
                 stride(j) = 1
 2           continue
-            err = nf90mpi_get_var_all(BAD_ID, i, value, start, &
-                        edge, stride)
+            err = nf90mpi_get_var_all(BAD_ID, i, value, start, edge, stride)
             if (err .ne. NF90_EBADID) &
                 call errore('bad ncid: ', err)
-            err = nf90mpi_get_var_all(ncid, BAD_VARID, value, &
-                        start, edge, stride) 
+            err = nf90mpi_get_var_all(ncid, BAD_VARID, value, start, edge, stride) 
             if (err .ne. NF90_ENOTVAR) &
                 call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
                 start(j) = var_shape(j,i) + 1
-                err = nf90mpi_get_var_all(ncid, i, value, start, &
-                                     edge, stride) 
+                err = nf90mpi_get_var_all(ncid, i, value, start, edge, stride) 
                 if (.not. canConvert) then
                     if (err .ne. NF90_ECHAR) &
                         call errore('conversion: ', err)
@@ -579,8 +577,7 @@ define([TEST_NFMPI_GET_VARS],dnl
                 endif
                 start(j) = 1
                 edge(j) = var_shape(j,i) + 1
-                err = nf90mpi_get_var_all(ncid, i, value, start, &
-                                     edge, stride) 
+                err = nf90mpi_get_var_all(ncid, i, value, start, edge, stride) 
                 if (.not. canConvert) then
                     if (err .ne. NF90_ECHAR) &
                         call errore('conversion: ', err)
@@ -590,8 +587,7 @@ define([TEST_NFMPI_GET_VARS],dnl
                 endif
                 edge(j) = 1
                 stride(j) = 0
-                err = nf90mpi_get_var_all(ncid, i, value, start, &
-                                     edge, stride)
+                err = nf90mpi_get_var_all(ncid, i, value, start, edge, stride)
                 if (.not. canConvert) then
                     if (err .ne. NF90_ECHAR) &
                         call errore('conversion: ', err)
@@ -601,18 +597,71 @@ define([TEST_NFMPI_GET_VARS],dnl
                 endif
                 stride(j) = 1
 3           continue
+
+!           /* Check non-scalars for correct error returned even when */
+!           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 4, j = 1, var_rank(i)
+                    edge(j) = 0
+4               continue
+                err = nf90mpi_get_var_all(BAD_ID, i, value, start, edge, stride)
+                if (err .ne. NF90_EBADID)  &
+                    call errore('bad ncid: ', err)
+                err = nf90mpi_get_var_all(ncid, BAD_VARID, value, start, edge, stride)
+                if (err .ne. NF90_ENOTVAR)  &
+                    call errore('bad var id: ', err)
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_get_var_all(ncid, i, value, start, edge, stride)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .ne. NF90_NOERR) &
+                            call error(nf90mpi_strerror(err))
+#else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+#endif
+                    endif
+                    start(j) = var_shape(j,i) + 2
+                    err = nf90mpi_get_var_all(ncid, i, value, start, edge, stride)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
+                err = nf90mpi_get_var_all(ncid, i, value, start, edge, stride)
+                if (canConvert) then
+                    if (err .ne. NF90_NOERR)  &
+                        call error(nf90mpi_strerror(err))
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                endif
+                do 6, j = 1, var_rank(i)
+                    edge(j) = 1
+6               continue
+            endif
+
 !           Choose a random point dividing each dim into 2 parts
 !           get 2^rank (nslabs) slabs so defined
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
 !           bits of k determine whether to get lower or upper part of dim
 !           choose random stride from 1 to edge
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, j-1), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -626,19 +675,19 @@ define([TEST_NFMPI_GET_VARS],dnl
                         sstride(j) = 1
                     end if
                     nstarts = nstarts * stride(j)
-6               continue
-                do 7, m = 1, INT(nstarts)
+9               continue
+                do 10, m = 1, INT(nstarts)
                     err = index2indexes(m, var_rank(i), sstride,  &
                                         index)
                     if (err .ne. NF90_NOERR) &
                         call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) /  &
                                         stride(j)
                         nels = nels * count(j)
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
 !                   Random choice of forward or backward 
 !    /* TODO
 !                   if ( roll(2) ) then
@@ -650,19 +699,18 @@ define([TEST_NFMPI_GET_VARS],dnl
 !    */
                     allInIntRange = .true.
                     allInExtRange = .true.
-                    do 9, j = 1, INT(nels)
+                    do 12, j = 1, INT(nels)
                         err = index2indexes(j, var_rank(i), count,  &
                                             index2)
                         if (err .ne. NF90_NOERR) &
                             call error('error in index2indexes() 1')
-                        do 10, d = 1, var_rank(i)
+                        do 13, d = 1, var_rank(i)
                             index2(d) = index(d) + (index2(d)-1) *  &
                                         stride(d)
-10                      continue
+13                      continue
                         expect(j) = hash4(var_type(i), var_rank(i),  &
                                           index2, NFT_ITYPE($1))
-                        if (inRange3(expect(j),var_type(i), &
-                                     NFT_ITYPE($1))) then
+                        if (inRange3(expect(j),var_type(i), NFT_ITYPE($1))) then
                             allInIntRange =  &
                                 allInIntRange .and. &
                                 in_internal_range(NFT_ITYPE($1),  &
@@ -670,7 +718,7 @@ define([TEST_NFMPI_GET_VARS],dnl
                         else
                             allInExtRange = .false.
                         end if
-9                   continue
+12                  continue
                     err = nf90mpi_get_var_all(ncid, i, value, index, &
                                          count, stride)
                     if (canConvert) then
@@ -687,7 +735,7 @@ define([TEST_NFMPI_GET_VARS],dnl
                                 err .ne. NF90_ERANGE) &
                                 call errore('OK or Range error: ', err)
                         end if
-                        do 11, j = 1, INT(nels)
+                        do 14, j = 1, INT(nels)
                             if (inRange3(expect(j),var_type(i), &
                                 NFT_ITYPE($1)) .and. &
                                 in_internal_range(NFT_ITYPE($1),  &
@@ -712,13 +760,13 @@ define([TEST_NFMPI_GET_VARS],dnl
                                     nok = nok + 1
                                 end if
                             end if
-11                      continue
+14                      continue
                     else
                         if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
                             call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 
 1       continue
         err = nf90mpi_close(ncid)
@@ -829,19 +877,72 @@ define([TEST_NFMPI_GET_VARM],dnl
                 endif
                 stride(j) = 1
 3           continue
+
+!           /* Check non-scalars for correct error returned even when */
+!           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 4, j = 1, var_rank(i)
+                    edge(j) = 0
+4               continue
+                err = nf90mpi_get_var_all(BAD_ID, i, value, start, edge, stride, imap)
+                if (err .ne. NF90_EBADID)  &
+                    call errore('bad ncid: ', err)
+                err = nf90mpi_get_var_all(ncid, BAD_VARID, value, start, edge, stride, imap)
+                if (err .ne. NF90_ENOTVAR)  &
+                    call errore('bad var id: ', err)
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_get_var_all(ncid, i, value, start, edge, stride, imap)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .ne. NF90_NOERR) &
+                            call error(nf90mpi_strerror(err))
+#else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+#endif
+                    endif
+                    start(j) = var_shape(j,i) + 2
+                    err = nf90mpi_get_var_all(ncid, i, value, start, edge, stride, imap)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
+                err = nf90mpi_get_var_all(ncid, i, value, start, edge, stride, imap)
+                if (canConvert) then
+                    if (err .ne. NF90_NOERR)  &
+                        call error(nf90mpi_strerror(err))
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                endif
+                do 6, j = 1, var_rank(i)
+                    edge(j) = 1
+6               continue
+            endif
+
 !           Choose a random point dividing each dim into 2 parts 
 !           get 2^rank (nslabs) slabs so defined 
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
 !           /* bits of k determine whether to get lower or upper part 
 !            * of dim
 !            * choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift((k-1), -(j-1)), 2) .ne. 0) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -856,18 +957,18 @@ define([TEST_NFMPI_GET_VARM],dnl
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * stride(j)
-6               continue
-                do 7, m = 1, INT(nstarts)
+9               continue
+                do 10, m = 1, INT(nstarts)
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF90_NOERR) &
                         call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) /  &
                                         stride(j)
                         nels = nels * count(j)
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
 !                   Random choice of forward or backward 
 !    /* TODO
 !                   if ( roll(2) ) then
@@ -879,25 +980,24 @@ define([TEST_NFMPI_GET_VARM],dnl
 !     */
                     if (var_rank(i) .gt. 0) then
                         imap(1) = 1
-                        do 9, j = 2, var_rank(i)
+                        do 12, j = 2, var_rank(i)
                             imap(j) = imap(j-1) * count(j-1)
-9                       continue
+12                      continue
                     end if
                     allInIntRange = .true.
                     allInExtRange = .true.
-                    do 10, j = 1, INT(nels)
+                    do 13, j = 1, INT(nels)
                         err = index2indexes(j, var_rank(i), count,  &
                                             index2)
                         if (err .ne. NF90_NOERR) &
                             call error('error in index2indexes 1')
-                        do 11, d = 1, var_rank(i)
+                        do 14, d = 1, var_rank(i)
                             index2(d) = index(d) + (index2(d)-1) *  &
                                         stride(d)
-11                      continue
+14                      continue
                         expect(j) = hash4(var_type(i), var_rank(i),  &
                                           index2, NFT_ITYPE($1))
-                        if (inRange3(expect(j),var_type(i), &
-                                     NFT_ITYPE($1))) then
+                        if (inRange3(expect(j),var_type(i), NFT_ITYPE($1))) then
                             allInIntRange =  &
                                 allInIntRange .and. &
                                 in_internal_range(NFT_ITYPE($1), &
@@ -905,7 +1005,7 @@ define([TEST_NFMPI_GET_VARM],dnl
                         else
                             allInExtRange = .false.
                         end if
-10                  continue
+13                  continue
                     err = nf90mpi_get_var_all(ncid,i,value,index,count, &
                                          stride,imap)
                     if (canConvert) then
@@ -922,7 +1022,7 @@ define([TEST_NFMPI_GET_VARM],dnl
                                 err .ne. NF90_ERANGE) &
                                 call errore('OK or Range error: ', err)
                         end if
-                        do 12, j = 1, INT(nels)
+                        do 15, j = 1, INT(nels)
                             if (inRange3(expect(j),var_type(i), &
                                          NFT_ITYPE($1)) .and. &
                                 in_internal_range(NFT_ITYPE($1), &
@@ -948,13 +1048,13 @@ define([TEST_NFMPI_GET_VARM],dnl
                                     nok = nok + 1
                                 end if
                             end if
-12                      continue
+15                      continue
                     else
                         if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
                             call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 1       continue
         err = nf90mpi_close(ncid)
         if (err .ne. NF90_NOERR) &
@@ -1081,14 +1181,7 @@ define([TEST_NFMPI_GET_ATT],dnl
         end
 ])dnl
 
-divert(0)dnl
-dnl If you see this line, you can ignore the next one.
-! Do not edit this file. It is produced from the corresponding .m4 source */
-
-!
-!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
-!  See COPYRIGHT notice in top-level directory.
-!
+dnl divert(0)dnl
 
 TEST_NFMPI_GET_VAR1(text)
 #ifdef NF_INT1_T
diff --git a/test/nf90_test/test_iget.m4 b/test/nf90_test/test_iget.m4
index 1bed4ef..d73f9d1 100644
--- a/test/nf90_test/test_iget.m4
+++ b/test/nf90_test/test_iget.m4
@@ -1,11 +1,18 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
 dnl
-dnl  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
-dnl  See COPYRIGHT notice in top-level directory.
+dnl This file is supposed to be the same as PnetCDF's test_iget.m4
 dnl
-dnl $Id: test_iget.m4 2081 2015-08-20 01:00:47Z wkliao $
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
 dnl
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_iget.m4 2619 2016-11-14 22:50:46Z wkliao $
 
-divert(-1)
+dnl divert(-1)
 
 dnl This is m4 source.
 dnl Process using m4 to produce FORTRAN language file.
@@ -113,8 +120,6 @@ define([TEST_NFMPI_IGET_VAR1],[dnl
             do 3, j = 1, var_rank(i)
                 index(j) = var_shape(j,i) + 1
                 err = nf90mpi_iget_var(ncid,i,value, reqid(1),index)
-                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
                 if (.not. canConvert) then
                     if (err .ne. NF90_ECHAR) &
                         call errore('conversion: ', err)
@@ -312,8 +317,7 @@ define([TEST_NFMPI_IGET_VARA],[dnl
 
         nok = 0
 
-        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
-                         ncid)
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, ncid)
         if (err .ne. NF90_NOERR) &
             call errore('nf90mpi_open: ', err)
         do 1, i = 1, numVars
@@ -334,46 +338,66 @@ define([TEST_NFMPI_IGET_VARA],[dnl
             do 3, j = 1, var_rank(i)
                 start(j) = var_shape(j,i) + 1
                 err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
-                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                if (canConvert .and. err .ne. NF90_EINVALCOORDS) &
-                    call errore('bad index: ', err)
+                if (.NOT. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad index: ', err)
+                endif
                 start(j) = 1
                 edge(j) = var_shape(j,i) + 1
                 err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
-                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                if (canConvert .and. err .ne. NF90_EEDGE) &
-                    call errore('bad edge: ', err)
+                if (.NOT. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
                 edge(j) = 1
 3           continue
 
 !           /* Check non-scalars for correct error returned even when */
 !           /* there is nothing to get (edge(j).eq.0) */
             if (var_rank(i) .gt. 0) then
-                do 10, j = 1, var_rank(i)
+                do 4, j = 1, var_rank(i)
                     edge(j) = 0
-10              continue
+4               continue
                 err = nf90mpi_iget_var(BAD_ID, i, value,reqid(1), start, edge)
                 if (err .ne. NF90_EBADID)  &
                     call errore('bad ncid: ', err)
                 err = nf90mpi_iget_var(ncid, BAD_VARID, value,reqid(1), start, edge)
                 if (err .ne. NF90_ENOTVAR)  &
                     call errore('bad var id: ', err)
-                do 11, j = 1, var_rank(i)
-                    if (var_dimid(j,i) .gt. 1) then     !/* skip record dim */
-                        start(j) = var_shape(j,i) + 1
-                        err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
-                        if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                            err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                        if (canConvert .and. err .ne. NF90_EINVALCOORDS) &
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .ne. NF90_NOERR) &
+                            call error(nf90mpi_strerror(err))
+#else
+                        if (err .ne. NF90_EINVALCOORDS) &
                             call errore('bad start: ', err)
-                        start(j) = 1
+#endif
                     endif
-11              continue
+                    start(j) = var_shape(j,i) + 2
+                    err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
                 err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
-                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
                 if (canConvert) then
                     if (err .ne. NF90_NOERR) &
                         call error(nf90mpi_strerror(err))
@@ -381,22 +405,22 @@ define([TEST_NFMPI_IGET_VARA],[dnl
                     if (err .ne. NF90_ECHAR) &
                         call errore('wrong type: ', err)
                 endif
-                do 12, j = 1, var_rank(i)
+                do 6, j = 1, var_rank(i)
                     edge(j) = 1
-12              continue
+6               continue
             endif
 
 !           Choose a random point dividing each dim into 2 parts
 !           get 2^rank (nslabs) slabs so defined
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
 !           bits of k determine whether to get lower or upper part of dim 
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nels = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift((k-1), -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -405,16 +429,16 @@ define([TEST_NFMPI_IGET_VARA],[dnl
                         edge(j) = var_shape(j,i) - mid(j)
                     end if
                     nels = nels * edge(j)
-6               continue
+9               continue
                 allInIntRange = .true.
                 allInExtRange = .true.
-                do 7, j = 1, INT(nels)
+                do 10, j = 1, INT(nels)
                     err = index2indexes(j, var_rank(i), edge, index)
                     if (err .ne. NF90_NOERR) &
                         call error('error in index2indexes 1')
-                    do 8, d = 1, var_rank(i)
+                    do 11, d = 1, var_rank(i)
                         index(d) = index(d) + start(d) - 1
-8                   continue
+11                  continue
                     expect(j) = hash4(var_type(i), var_rank(i), index,  &
                                       NFT_ITYPE($1))
                     if (inRange3(expect(j),var_type(i),  &
@@ -425,7 +449,7 @@ define([TEST_NFMPI_IGET_VARA],[dnl
                     else
                         allInExtRange = .false.
                     end if
-7               continue
+10              continue
                 err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
                 if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
                     err_w = nf90mpi_wait_all(ncid,1,reqid,st)
@@ -433,8 +457,7 @@ define([TEST_NFMPI_IGET_VARA],[dnl
                     if (allInExtRange) then
                         if (allInIntRange) then
                             if (st(1) .ne. 0) &
-                                call errore( &
-                                    'nf90mpi_iget_var:',st(1))
+                                call errore('nf90mpi_iget_var:',st(1))
                         else
                             if (st(1) .ne. NF90_ERANGE) &
                                 call errore('Range error: ', st(1))
@@ -443,7 +466,7 @@ define([TEST_NFMPI_IGET_VARA],[dnl
                         if (st(1) .ne. 0 .and. st(1) .ne. NF90_ERANGE) &
                             call errore('OK or Range error: ', st(1))
                     end if
-                    do 9, j = 1, INT(nels)
+                    do 12, j = 1, INT(nels)
                         if (inRange3(expect(j),var_type(i), &
                                      NFT_ITYPE($1)) .and. &
                             in_internal_range(NFT_ITYPE($1), expect(j))) &
@@ -457,10 +480,8 @@ define([TEST_NFMPI_IGET_VARA],[dnl
                                 if (verbose) then
                                     call error(' ')
                                     call errori('varid: ', i)
-                                    call errorc('var_name: ', &
-                                        var_name(i))
-                                    call errori('element number: %d ',  &
-                                                j)
+                                    call errorc('var_name: ', var_name(i))
+                                    call errori('element number: %d ', j)
                                     call errord('expect: ', expect(j))
                                     call errord('got: ', val)
                                 end if
@@ -468,12 +489,12 @@ define([TEST_NFMPI_IGET_VARA],[dnl
                                 nok = nok + 1
                             end if
                         end if
-9                   continue
+12                  continue
                 else
                     if (nels .gt. 0  .and. err .ne. NF90_ECHAR) &
                         call errore('wrong type: ', err)
                 end if
-5           continue
+8           continue
 1       continue
         err = nf90mpi_close(ncid)
         if (err .ne. NF90_NOERR) &
@@ -525,8 +546,7 @@ define([TEST_NFMPI_IGET_VARS],dnl
 
         nok = 0
 
-        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
-                         ncid)
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, ncid)
         if (err .ne. NF90_NOERR) &
             call errore('nf90mpi_open: ', err)
         do 1, i = 1, numVars
@@ -548,8 +568,6 @@ define([TEST_NFMPI_IGET_VARS],dnl
             do 3, j = 1, var_rank(i)
                 start(j) = var_shape(j,i) + 1
                 err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride)
-                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
                 if (.not. canConvert) then
                     if (err .ne. NF90_ECHAR) &
                         call errore('conversion: ', err)
@@ -560,8 +578,6 @@ define([TEST_NFMPI_IGET_VARS],dnl
                 start(j) = 1
                 edge(j) = var_shape(j,i) + 1
                 err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride)
-                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
                 if (.not. canConvert) then
                     if (err .ne. NF90_ECHAR) &
                         call errore('conversion: ', err)
@@ -572,8 +588,6 @@ define([TEST_NFMPI_IGET_VARS],dnl
                 edge(j) = 1
                 stride(j) = 0
                 err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride)
-                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
                 if (.not. canConvert) then
                     if (err .ne. NF90_ECHAR) &
                         call errore('conversion: ', err)
@@ -583,18 +597,71 @@ define([TEST_NFMPI_IGET_VARS],dnl
                 endif
                 stride(j) = 1
 3           continue
-!               Choose a random point dividing each dim into 2 parts
-!               get 2^rank (nslabs) slabs so defined
+
+!           /* Check non-scalars for correct error returned even when */
+!           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 4, j = 1, var_rank(i)
+                    edge(j) = 0
+4               continue
+                err = nf90mpi_iget_var(BAD_ID, i, value,reqid(1), start, edge, stride)
+                if (err .ne. NF90_EBADID)  &
+                    call errore('bad ncid: ', err)
+                err = nf90mpi_iget_var(ncid, BAD_VARID, value,reqid(1), start, edge, stride)
+                if (err .ne. NF90_ENOTVAR)  &
+                    call errore('bad var id: ', err)
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .ne. NF90_NOERR) &
+                            call error(nf90mpi_strerror(err))
+#else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+#endif
+                    endif
+                    start(j) = var_shape(j,i) + 2
+                    err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride)
+                if (canConvert) then
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                endif
+                do 6, j = 1, var_rank(i)
+                    edge(j) = 1
+6               continue
+            endif
+
+!           Choose a random point dividing each dim into 2 parts
+!           get 2^rank (nslabs) slabs so defined
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
 !           bits of k determine whether to get lower or upper part of dim
 !           choose random stride from 1 to edge
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, j-1), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -608,19 +675,19 @@ define([TEST_NFMPI_IGET_VARS],dnl
                         sstride(j) = 1
                     end if
                     nstarts = nstarts * stride(j)
-6               continue
-                do 7, m = 1, INT(nstarts)
+9               continue
+                do 10, m = 1, INT(nstarts)
                     err = index2indexes(m, var_rank(i), sstride,  &
                                         index)
                     if (err .ne. NF90_NOERR) &
                         call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) /  &
                                         stride(j)
                         nels = nels * count(j)
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
 !                   Random choice of forward or backward 
 !    /* TODO
 !                   if ( roll(2) ) then
@@ -632,15 +699,15 @@ define([TEST_NFMPI_IGET_VARS],dnl
 !    */
                     allInIntRange = .true.
                     allInExtRange = .true.
-                    do 9, j = 1, INT(nels)
+                    do 12, j = 1, INT(nels)
                         err = index2indexes(j, var_rank(i), count,  &
                                             index2)
                         if (err .ne. NF90_NOERR) &
                             call error('error in index2indexes() 1')
-                        do 10, d = 1, var_rank(i)
+                        do 13, d = 1, var_rank(i)
                             index2(d) = index(d) + (index2(d)-1) *  &
                                         stride(d)
-10                      continue
+13                      continue
                         expect(j) = hash4(var_type(i), var_rank(i),  &
                                           index2, NFT_ITYPE($1))
                         if (inRange3(expect(j),var_type(i), &
@@ -652,7 +719,7 @@ define([TEST_NFMPI_IGET_VARS],dnl
                         else
                             allInExtRange = .false.
                         end if
-9                   continue
+12                  continue
                     err = nf90mpi_iget_var(ncid, i,value,reqid(1), index, count,stride)
                     if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
                         err_w = nf90mpi_wait_all(ncid,1,reqid,st)
@@ -669,7 +736,7 @@ define([TEST_NFMPI_IGET_VARS],dnl
                             if (st(1) .ne. 0 .and. st(1) .ne. NF90_ERANGE) &
                                 call errore('OK or Range error: ',st(1))
                         end if
-                        do 11, j = 1, INT(nels)
+                        do 14, j = 1, INT(nels)
                             if (inRange3(expect(j),var_type(i), &
                                 NFT_ITYPE($1)) .and. &
                                 in_internal_range(NFT_ITYPE($1),  &
@@ -677,30 +744,26 @@ define([TEST_NFMPI_IGET_VARS],dnl
                                 val = ARITH3($1, value, j)
                                 if (.not.equal(val, expect(j), &
                                     var_type(i), NFT_ITYPE($1))) then
-                                    call error( &
-                                        'value read not that expected')
+                                    call error('value read not that expected')
                                     if (verbose) then
                                         call error(' ')
                                         call errori('varid: ', i)
-                                        call errorc('var_name: ',  &
-                                                    var_name(i))
-                                        call errori('element number: ', &
-                                                    j)
-                                        call errord('expect: ',  &
-                                                    expect(j))
+                                        call errorc('var_name: ',var_name(i))
+                                        call errori('element number: ', j)
+                                        call errord('expect: ', expect(j))
                                         call errord('got: ', val)
                                     end if
                                 else
                                     nok = nok + 1
                                 end if
                             end if
-11                      continue
+14                      continue
                     else
                         if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
                             call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 
 1       continue
         err = nf90mpi_close(ncid)
@@ -778,8 +841,6 @@ define([TEST_NFMPI_IGET_VARM],dnl
             do 3, j = 1, var_rank(i)
                 start(j) = var_shape(j,i) + 1
                 err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride, imap)
-                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
                 if (.not. canConvert) then
                     if (err .ne. NF90_ECHAR) &
                         call errore('conversion: ', err)
@@ -790,8 +851,6 @@ define([TEST_NFMPI_IGET_VARM],dnl
                 start(j) = 1
                 edge(j) = var_shape(j,i) + 1
                 err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride, imap)
-                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
                 if (.not. canConvert) then
                     if (err .ne. NF90_ECHAR) &
                         call errore('conversion: ', err)
@@ -802,8 +861,6 @@ define([TEST_NFMPI_IGET_VARM],dnl
                 edge(j) = 1
                 stride(j) = 0
                 err = nf90mpi_iget_var(ncid, i, value, reqid(1), start, edge, stride, imap)
-                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
                 if (.not. canConvert) then
                     if (err .ne. NF90_ECHAR) &
                         call errore('conversion: ', err)
@@ -813,19 +870,72 @@ define([TEST_NFMPI_IGET_VARM],dnl
                 endif
                 stride(j) = 1
 3           continue
+
+!           /* Check non-scalars for correct error returned even when */
+!           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 4, j = 1, var_rank(i)
+                    edge(j) = 0
+4               continue
+                err = nf90mpi_iget_var(BAD_ID, i, value,reqid(1), start, edge, stride, imap)
+                if (err .ne. NF90_EBADID)  &
+                    call errore('bad ncid: ', err)
+                err = nf90mpi_iget_var(ncid, BAD_VARID, value,reqid(1), start, edge, stride, imap)
+                if (err .ne. NF90_ENOTVAR)  &
+                    call errore('bad var id: ', err)
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride, imap)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .ne. NF90_NOERR) &
+                            call error(nf90mpi_strerror(err))
+#else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+#endif
+                    endif
+                    start(j) = var_shape(j,i) + 2
+                    err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride, imap)
+                    if (.NOT. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride, imap)
+                if (canConvert) then
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                endif
+                do 6, j = 1, var_rank(i)
+                    edge(j) = 1
+6               continue
+            endif
+
 !           Choose a random point dividing each dim into 2 parts 
 !           get 2^rank (nslabs) slabs so defined 
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
 !           /* bits of k determine whether to get lower or upper part 
 !            * of dim
 !            * choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift((k-1), -(j-1)), 2) .ne. 0) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -840,18 +950,18 @@ define([TEST_NFMPI_IGET_VARM],dnl
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * stride(j)
-6               continue
-                do 7, m = 1, INT(nstarts)
+9               continue
+                do 10, m = 1, INT(nstarts)
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF90_NOERR) &
                         call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) /  &
                                         stride(j)
                         nels = nels * count(j)
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
 !                   Random choice of forward or backward 
 !    /* TODO
 !                   if ( roll(2) ) then
@@ -863,21 +973,21 @@ define([TEST_NFMPI_IGET_VARM],dnl
 !     */
                     if (var_rank(i) .gt. 0) then
                         imap(1) = 1
-                        do 9, j = 2, var_rank(i)
+                        do 12, j = 2, var_rank(i)
                             imap(j) = imap(j-1) * count(j-1)
-9                       continue
+12                      continue
                     end if
                     allInIntRange = .true.
                     allInExtRange = .true.
-                    do 10, j = 1, INT(nels)
+                    do 13, j = 1, INT(nels)
                         err = index2indexes(j, var_rank(i), count,  &
                                             index2)
                         if (err .ne. NF90_NOERR) &
                             call error('error in index2indexes 1')
-                        do 11, d = 1, var_rank(i)
+                        do 14, d = 1, var_rank(i)
                             index2(d) = index(d) + (index2(d)-1) *  &
                                         stride(d)
-11                      continue
+14                      continue
                         expect(j) = hash4(var_type(i), var_rank(i),  &
                                           index2, NFT_ITYPE($1))
                         if (inRange3(expect(j),var_type(i), &
@@ -889,7 +999,7 @@ define([TEST_NFMPI_IGET_VARM],dnl
                         else
                             allInExtRange = .false.
                         end if
-10                  continue
+13                  continue
                     err = nf90mpi_iget_var(ncid,i, value, reqid(1), index, count, stride, imap)
                     if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
                         err_w = nf90mpi_wait_all(ncid,1,reqid,st)
@@ -906,7 +1016,7 @@ define([TEST_NFMPI_IGET_VARM],dnl
                             if (st(1) .ne. 0 .and. st(1) .ne. NF90_ERANGE) &
                                 call errore('OK or Range error: ',st(1))
                         end if
-                        do 12, j = 1, INT(nels)
+                        do 15, j = 1, INT(nels)
                             if (inRange3(expect(j),var_type(i), &
                                          NFT_ITYPE($1)) .and. &
                                 in_internal_range(NFT_ITYPE($1), &
@@ -915,30 +1025,26 @@ define([TEST_NFMPI_IGET_VARM],dnl
                                 if (.not.equal(val, expect(j), &
                                                var_type(i),  &
                                                NFT_ITYPE($1))) then
-                                    call error( &
-                                        'value read not that expected')
+                                    call error('value read not that expected')
                                     if (verbose) then
                                         call error(' ')
                                         call errori('varid: ', i)
-                                        call errorc('var_name: ',  &
-                                                var_name(i))
-                                        call errori('element number: ', &
-                                                    j)
-                                        call errord('expect: ',  &
-                                                    expect(j))
+                                        call errorc('var_name: ', var_name(i))
+                                        call errori('element number: ', j)
+                                        call errord('expect: ', expect(j))
                                         call errord('got: ', val)
                                     end if
                                 else
                                     nok = nok + 1
                                 end if
                             end if
-12                      continue
+15                      continue
                     else
                         if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
                             call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 1       continue
         err = nf90mpi_close(ncid)
         if (err .ne. NF90_NOERR) &
@@ -947,14 +1053,7 @@ define([TEST_NFMPI_IGET_VARM],dnl
         end
 ])dnl
 
-divert(0)dnl
-dnl If you see this line, you can ignore the next one.
-! Do not edit this file. It is produced from the corresponding .m4 source */
-
-!
-!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
-!  See COPYRIGHT notice in top-level directory.
-!
+dnl divert(0)dnl
 
 TEST_NFMPI_IGET_VAR1(text)
 #ifdef NF_INT1_T
diff --git a/test/nf90_test/test_iput.m4 b/test/nf90_test/test_iput.m4
index fc7fa36..fa1a8fe 100644
--- a/test/nf90_test/test_iput.m4
+++ b/test/nf90_test/test_iput.m4
@@ -1,11 +1,18 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
 dnl
-dnl  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
-dnl  See COPYRIGHT notice in top-level directory.
+dnl This file is supposed to be the same as PnetCDF's test_iput.m4
 dnl
-dnl $Id: test_iput.m4 2156 2015-10-12 01:15:25Z wkliao $
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
 dnl
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_iput.m4 2619 2016-11-14 22:50:46Z wkliao $
 
-divert(-1)
+dnl divert(-1)
 
 dnl This is m4 source.
 dnl Process using m4 to produce FORTRAN language file.
@@ -149,8 +156,7 @@ define([TEST_NFMPI_IPUT_VAR1],dnl
         value = MAKE_TYPE($1, 5)!/* any value would do - only for error cases */
 
         flags = IOR(NF90_CLOBBER, extra_flags)
-        err = nf90mpi_create(comm, scratch, flags, info, &
-                           ncid)
+        err = nf90mpi_create(comm, scratch, flags, info, ncid)
         if (err .ne. NF90_NOERR) then
             call errore('nf90mpi_create: ', err)
             return
@@ -173,28 +179,23 @@ define([TEST_NFMPI_IPUT_VAR1],dnl
             if (err .ne. NF90_ENOTVAR)  &
                 call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .gt. 1) then         !/* skip record dim */
-                    index(j) = var_shape(j,i) + 1
-                    err = nf90mpi_iput_var(ncid, i, value(1:1),reqid(1), index)
-                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EINVALCOORDS) &
-                            call errore('bad index: ', err)
-                    endif
-                    index(j) = 0
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                index(j) = var_shape(j,i) + 1
+                err = nf90mpi_iput_var(ncid, i, value(1:1),reqid(1), index)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad index: ', err)
+                endif
+                index(j) = 0
 3           continue
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
-                                    index)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), index)
                 if (err .ne. NF90_NOERR)  &
                     call error('error in index2indexes 1')
-                val = hash_$1(var_type(i),var_rank(i), &
-                                  index, NFT_ITYPE($1))
+                val = hash_$1(var_type(i),var_rank(i), index, NFT_ITYPE($1))
                 MAKE_TYPE2($1, value, val)
                 err = nf90mpi_iput_var(ncid, i, value(1:1), reqid(1), index)
                 if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
@@ -254,8 +255,7 @@ define([TEST_NFMPI_IPUT_VAR],dnl
         integer err_w, reqid(1), st(1)
 
         flags = IOR(NF90_CLOBBER, extra_flags)
-        err = nf90mpi_create(comm, scratch, flags, info, &
-                           ncid)
+        err = nf90mpi_create(comm, scratch, flags, info, ncid)
         if (err .ne. NF90_NOERR) then
             call errore('nf90mpi_create: ', err)
             return
@@ -280,8 +280,7 @@ define([TEST_NFMPI_IPUT_VAR],dnl
 3           continue
             allInExtRange = .true.
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
-                                    index)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), index)
                 if (err .ne. NF90_NOERR)  &
                     call error('error in index2indexes 1')
                 val = hash_$1(var_type(i), var_rank(i), &
@@ -345,8 +344,7 @@ define([TEST_NFMPI_IPUT_VAR],dnl
 6               continue
                 allInExtRange = .true.
                 do 7, j = 1, INT(nels)
-                    err = index2indexes(j, var_rank(i), var_shape(1,i),  &
-                                    index)
+                    err = index2indexes(j, var_rank(i), var_shape(1,i), index)
                     if (err .ne. NF90_NOERR)  &
                         call error('error in index2indexes()')
                     val = hash_$1(var_type(i), var_rank(i), &
@@ -420,8 +418,7 @@ define([TEST_NFMPI_IPUT_VARA],dnl
         integer err_w, reqid(1), st(1)
 
         flags = IOR(NF90_CLOBBER, extra_flags)
-        err = nf90mpi_create(comm, scratch, flags, info, &
-                           ncid)
+        err = nf90mpi_create(comm, scratch, flags, info, ncid)
         if (err .ne. NF90_NOERR) then
             call errore('nf90mpi_create: ', err)
             return
@@ -451,63 +448,67 @@ define([TEST_NFMPI_IPUT_VARA],dnl
             if (err .ne. NF90_ENOTVAR)  &
                 call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
-                    start(j) = var_shape(j,i) + 1
-                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
-                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                        ! NF90_ERANGE is not a fatal error
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EINVALCOORDS) &
-                            call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
-                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                        ! NF90_ERANGE is not a fatal error
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EEDGE) &
-                            call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
 3           continue
 
 !           /* Check correct error returned even when nothing to put */
-            do 20, j = 1, var_rank(i)
+            do 4, j = 1, var_rank(i)
                   edge(j) = 0
-20          continue
+4           continue
             err = nf90mpi_iput_var(BAD_ID, i, value,reqid(1), start, edge)
             if (err .ne. NF90_EBADID)  &
                 call errore('bad ncid: ', err)
             err = nf90mpi_iput_var(ncid, BAD_VARID, value,reqid(1), start, edge)
             if (err .ne. NF90_ENOTVAR)  &
                 call errore('bad var id: ', err)
-            do 21, j = 1, var_rank(i)
-                if (var_dimid(j,i) .gt. 1) then     ! skip record dim
-                    start(j) = var_shape(j,i) + 1
-                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
-                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                        err_w = nf90mpi_wait_all(ncid, 1, reqid, st)
-                        ! NF90_ERANGE is not a fatal error
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EINVALCOORDS) &
-                            call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+#else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+#endif
+                endif
+                start(j) = var_shape(j,i) + 2
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
                 endif
-21          continue
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
             err = nf90mpi_iput_var(ncid, i, value, reqid(1), start, edge)
             if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
                 err_w = nf90mpi_wait_all(ncid,1,reqid,st)
@@ -518,22 +519,21 @@ define([TEST_NFMPI_IPUT_VARA],dnl
                 if (err .ne. NF90_ECHAR) &
                     call errore('wrong type: ', err)
             endif
-            do 22, j = 1, var_rank(i)
-                  edge(j) = 1
-22          continue
-
+            do 6, j = 1, var_rank(i)
+                edge(j) = 1
+6           continue
 
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
-                !/* bits of k determine whether to put lower or upper part of dim */
-            do 5, k = 1, nslabs
+7           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            do 8, k = 1, nslabs
                 nels = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -542,22 +542,22 @@ define([TEST_NFMPI_IPUT_VARA],dnl
                         edge(j) = var_shape(j,i) - mid(j)
                     end if
                     nels = nels * edge(j)
-6               continue
+9               continue
                 allInExtRange = .true.
-                do 7, j = 1, INT(nels)
+                do 10, j = 1, INT(nels)
                     err = index2indexes(j, var_rank(i), edge, index)
                     if (err .ne. NF90_NOERR)  &
                         call error('error in index2indexes 1')
-                    do 8, d = 1, var_rank(i)
+                    do 11, d = 1, var_rank(i)
                         index(d) = index(d) + start(d) - 1
-8                   continue
+11                  continue
                     val = hash_$1(var_type(i), var_rank(i), &
                                   index, NFT_ITYPE($1))
                     MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
                     val = ARITH3($1, value, j)
                     allInExtRange = allInExtRange .and. &
                         inRange3(val, var_type(i), NFT_ITYPE($1))
-7               continue
+10              continue
                 err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
                 if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
                     err_w = nf90mpi_wait_all(ncid,1,reqid,st)
@@ -574,7 +574,7 @@ define([TEST_NFMPI_IPUT_VARA],dnl
                     if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
                         call errore('wrong type: ', err)
                 end if
-5           continue
+8           continue
 1       continue
 
         err = nf90mpi_close(ncid)
@@ -629,8 +629,7 @@ define([TEST_NFMPI_IPUT_VARS],dnl
         integer err_w, reqid(1), st(1)
 
         flags = IOR(NF90_CLOBBER, extra_flags)
-        err = nf90mpi_create(comm, scratch, flags, info, &
-                           ncid)
+        err = nf90mpi_create(comm, scratch, flags, info, ncid)
         if (err .ne. NF90_NOERR) then
             call errore('nf90mpi_create: ', err)
             return
@@ -660,57 +659,103 @@ define([TEST_NFMPI_IPUT_VARS],dnl
             if (err .ne. NF90_ENOTVAR)  &
                 call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    ! skip record dim
-                    start(j) = var_shape(j,i) + 1
-                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
-                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EINVALCOORDS) &
-                                call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
-                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EEDGE) &
-                            call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                    stride(j) = 0
-                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
-                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_ESTRIDE) &
-                            call errore('bad stride: ', err)
-                    endif
-                    stride(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_ESTRIDE) &
+                        call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
 3           continue
+
+!           /* Check correct error returned even when nothing to put */
+            do 4, j = 1, var_rank(i)
+                  edge(j) = 0
+4           continue
+            err = nf90mpi_iput_var(BAD_ID, i, value,reqid(1), start, edge, stride)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iput_var(ncid, BAD_VARID, value,reqid(1), start, edge, stride)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+#else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+#endif
+                endif
+                start(j) = var_shape(j,i) + 2
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nf90mpi_iput_var(ncid, i, value, reqid(1), start, edge, stride)
+            if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+            if (canConvert) then
+                if (st(1) .ne. 0)  &
+                    call error(nf90mpi_strerror(st(1)))
+            else
+                if (err .ne. NF90_ECHAR) &
+                    call errore('wrong type: ', err)
+            endif
+            do 6, j = 1, var_rank(i)
+                edge(j) = 1
+6           continue
+
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
             !/* bits of k determine whether to put lower or upper part of dim */
             !/* choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -725,17 +770,17 @@ define([TEST_NFMPI_IPUT_VARS],dnl
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * stride(j)
-6               continue
-                do 7, m = 1, INT(nstarts)
+9               continue
+                do 10, m = 1, INT(nstarts)
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF90_NOERR) &
                         call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) / stride(j)
                         nels = nels * count(j)
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
                     !/* Random choice of forward or backward */
 ! TODO
 !                   if ( roll(2) ) {
@@ -746,15 +791,15 @@ define([TEST_NFMPI_IPUT_VARS],dnl
 !                   }
 !
                     allInExtRange = .true.
-                    do 9, j = 1, INT(nels)
+                    do 12, j = 1, INT(nels)
                         err = index2indexes(j, var_rank(i), count,  &
                                             index2)
                         if (err .ne. NF90_NOERR) &
                             call error('error in index2indexes')
-                        do 10, d = 1, var_rank(i)
+                        do 13, d = 1, var_rank(i)
                             index2(d) = index(d) +  &
                                         (index2(d)-1) * stride(d)
-10                      continue
+13                      continue
                         val = hash_$1(var_type(i), var_rank(i), &
                                       index2, NFT_ITYPE($1))
                         MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
@@ -762,7 +807,7 @@ define([TEST_NFMPI_IPUT_VARS],dnl
                         allInExtRange = allInExtRange .and. &
                             inRange3(val, var_type(i),  &
                                      NFT_ITYPE($1))
-9                   continue
+12                  continue
                     err = nf90mpi_iput_var(ncid, i, value,reqid(1), index, count, stride)
                     if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
                         err_w = nf90mpi_wait_all(ncid,1,reqid,st)
@@ -778,8 +823,8 @@ define([TEST_NFMPI_IPUT_VARS],dnl
                         if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
                             call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 1       continue
 
         err = nf90mpi_close(ncid)
@@ -837,8 +882,7 @@ define([TEST_NFMPI_IPUT_VARM],dnl
         integer err_w, reqid(1), st(1)
 
         flags = IOR(NF90_CLOBBER, extra_flags)
-        err = nf90mpi_create(comm, scratch, flags, info, &
-                           ncid)
+        err = nf90mpi_create(comm, scratch, flags, info, ncid)
         if (err .ne. NF90_NOERR) then
             call errore('nf90mpi_create: ', err)
             return
@@ -865,65 +909,107 @@ define([TEST_NFMPI_IPUT_VARM],dnl
             err = nf90mpi_iput_var(BAD_ID, i, value,reqid(1), start, edge, stride, imap)
             if (err .ne. NF90_EBADID)  &
                 call errore('bad ncid: ', err)
-            err = nf90mpi_iput_var(ncid, BAD_VARID, &
-                                 value,reqid(1), start, edge, stride, imap)
+            err = nf90mpi_iput_var(ncid, BAD_VARID, value,reqid(1), start, edge, stride, imap)
             if (err .ne. NF90_ENOTVAR)  &
                 call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
-                    start(j) = var_shape(j,i) + 1
-                    err = nf90mpi_iput_var(ncid, i, &
-                                         value,reqid(1), start, edge, stride, imap)
-                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EINVALCOORDS) &
-                            call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nf90mpi_iput_var(ncid, i, &
-                                         value,reqid(1), start, edge, stride, imap)
-                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EEDGE) &
-                            call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                    stride(j) = 0
-                    err = nf90mpi_iput_var(ncid, i, &
-                                         value,reqid(1), start, edge, stride, imap)
-                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
-                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_ESTRIDE) &
-                            call errore('bad stride: ', err)
-                    endif
-                    stride(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_ESTRIDE) &
+                        call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
 3           continue
+
+!           /* Check correct error returned even when nothing to put */
+            do 4, j = 1, var_rank(i)
+                  edge(j) = 0
+4           continue
+            err = nf90mpi_iput_var(BAD_ID, i, value,reqid(1), start, edge, stride, imap)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iput_var(ncid, BAD_VARID, value,reqid(1), start, edge, stride, imap)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+#else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+#endif
+                endif
+                start(j) = var_shape(j,i) + 2
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nf90mpi_iput_var(ncid, i, value, reqid(1), start, edge, stride, imap)
+            if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+            if (canConvert) then
+                if (st(1) .ne. 0)  &
+                    call error(nf90mpi_strerror(st(1)))
+            else
+                if (err .ne. NF90_ECHAR) &
+                    call errore('wrong type: ', err)
+            endif
+            do 6, j = 1, var_rank(i)
+                edge(j) = 1
+6           continue
+
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
             !/* bits of k determine whether to put lower or upper part of dim */
             !/* choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -938,43 +1024,43 @@ define([TEST_NFMPI_IPUT_VARM],dnl
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * stride(j)
-6               continue
-                do 7, m = 1, INT(nstarts)
+9               continue
+                do 10, m = 1, INT(nstarts)
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF90_NOERR) &
                         call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) / stride(j)
                         nels = nels * count(j)
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
                     !/* Random choice of forward or backward */
 ! TODO
 !                   if ( roll(2) ) then
-!                       do 9, j = 1, var_rank(i)
+!                       do 12, j = 1, var_rank(i)
 !                           index(j) = index(j) +  &
 !                               (count(j) - 1) * stride(j)
 !                           stride(j) = -stride(j)
-!9                      continue
+!12                     continue
 !                   end if
 !
                     if (var_rank(i) .gt. 0) then
                         imap(1) = 1
-                        do 10, j = 2, var_rank(i)
+                        do 13, j = 2, var_rank(i)
                             imap(j) = imap(j-1) * count(j-1)
-10                      continue
+13                      continue
                     end if
                     allInExtRange = .true.
-                    do 11 j = 1, INT(nels)
+                    do 14 j = 1, INT(nels)
                         err = index2indexes(j, var_rank(i), count,  &
                                             index2)
                         if (err .ne. NF90_NOERR) &
                             call error('error in index2indexes')
-                        do 12, d = 1, var_rank(i)
+                        do 15, d = 1, var_rank(i)
                             index2(d) = index(d) +  &
                                 (index2(d)-1) * stride(d)
-12                      continue
+15                      continue
                         val = hash_$1(var_type(i),var_rank(i), &
                                       index2, NFT_ITYPE($1))
                         MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
@@ -982,7 +1068,7 @@ define([TEST_NFMPI_IPUT_VARM],dnl
                         allInExtRange = allInExtRange .and. &
                             inRange3(val, var_type(i),  &
                                      NFT_ITYPE($1))
-11                  continue
+14                  continue
                     err = nf90mpi_iput_var(ncid,i,&
                                          value,reqid(1), index, count, stride, imap)
                     if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
@@ -999,8 +1085,8 @@ define([TEST_NFMPI_IPUT_VARM],dnl
                         if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
                             call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 1       continue
 
         err = nf90mpi_close(ncid)
@@ -1017,14 +1103,7 @@ define([TEST_NFMPI_IPUT_VARM],dnl
 ])dnl
 
 
-divert(0)dnl
-dnl If you see this line, you can ignore the next one.
-! Do not edit this file. It is produced from the corresponding .m4 source */
-
-!
-!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
-!  See COPYRIGHT notice in top-level directory.
-!
+dnl divert(0)dnl
 
 TEST_NFMPI_IPUT_VAR1(text)
 #ifdef NF_INT1_T
diff --git a/test/nf90_test/test_put.m4 b/test/nf90_test/test_put.m4
index a1c9733..74e59bb 100644
--- a/test/nf90_test/test_put.m4
+++ b/test/nf90_test/test_put.m4
@@ -1,11 +1,18 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
 dnl
-dnl  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
-dnl  See COPYRIGHT notice in top-level directory.
+dnl This file is supposed to be the same as PnetCDF's test_put.m4
 dnl
-dnl $Id: test_put.m4 2156 2015-10-12 01:15:25Z wkliao $
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
 dnl
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_put.m4 2619 2016-11-14 22:50:46Z wkliao $
 
-divert(-1)
+dnl divert(-1)
 
 dnl This is m4 source.
 dnl Process using m4 to produce FORTRAN language file.
@@ -420,8 +427,7 @@ define([TEST_NFMPI_PUT_VAR1],dnl
         value = MAKE_TYPE($1, 5)!/* any value would do - only for error cases */
 
         flags = IOR(NF90_CLOBBER, extra_flags)
-        err = nf90mpi_create(comm, scratch, flags, info, &
-                           ncid)
+        err = nf90mpi_create(comm, scratch, flags, info, ncid)
         if (err .ne. NF90_NOERR) then
             call errore('nf90mpi_create: ', err)
             return
@@ -445,18 +451,17 @@ define([TEST_NFMPI_PUT_VAR1],dnl
             if (err .ne. NF90_ENOTVAR)  &
                 call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .gt. 1) then         !/* skip record dim */
-                    index(j) = var_shape(j,i) + 1
-                    err = nf90mpi_put_var(ncid, i, value(1:1), index)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EINVALCOORDS) &
-                            call errore('bad index: ', err)
-                    endif
-                    index(j) = 0
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                index(j) = var_shape(j,i) + 1
+                err = nf90mpi_put_var(ncid, i, value(1:1), index)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad index: ', err)
+                endif
+                index(j) = 0
 3           continue
             do 4, j = 1, var_nels(i)
                 err = index2indexes(j, var_rank(i), var_shape(1,i), index)
@@ -548,8 +553,7 @@ define([TEST_NFMPI_PUT_VAR],dnl
 3           continue
             allInExtRange = .true.
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
-                                    index)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), index)
                 if (err .ne. NF90_NOERR)  &
                     call error('error in index2indexes 1')
                 val = hash_$1(var_type(i), var_rank(i), &
@@ -608,8 +612,7 @@ define([TEST_NFMPI_PUT_VAR],dnl
 6               continue
                 allInExtRange = .true.
                 do 7, j = 1, INT(nels)
-                    err = index2indexes(j, var_rank(i), var_shape(1,i),  &
-                                    index)
+                    err = index2indexes(j, var_rank(i), var_shape(1,i), index)
                     if (err .ne. NF90_NOERR)  &
                         call error('error in index2indexes()')
                     val = hash_$1(var_type(i), var_rank(i), &
@@ -710,84 +713,90 @@ define([TEST_NFMPI_PUT_VARA],dnl
             if (err .ne. NF90_ENOTVAR)  &
                 call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
-                    start(j) = var_shape(j,i) + 1
-                    err = nf90mpi_put_var_all(ncid, i, value, start, edge)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EINVALCOORDS) &
-                            call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nf90mpi_put_var_all(ncid, i, value, start, edge)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EEDGE) &
-                            call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
 3           continue
 
 !           /* Check correct error returned even when nothing to put */
-            do 20, j = 1, var_rank(i)
+            do 4, j = 1, var_rank(i)
                 edge(j) = 0
-20          continue
+4           continue
             err = nf90mpi_put_var_all(BAD_ID, i, value, start, edge)
             if (err .ne. NF90_EBADID)  &
                 call errore('bad ncid: ', err)
             err = nf90mpi_put_var_all(ncid, BAD_VARID, value, start, edge)
             if (err .ne. NF90_ENOTVAR)  &
                 call errore('bad var id: ', err)
-            do 21, j = 1, var_rank(i)
-                if (var_dimid(j,i) .gt. 1) then     ! skip record dim
-                    start(j) = var_shape(j,i) + 1
-                    err = nf90mpi_put_var_all(ncid, i, value, start, edge)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EINVALCOORDS) &
-                            call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+#else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+#endif
                 endif
-21          continue
-
-! wkliao: this test below of put_vara is redundant and incorrectly uses the
-!         value[] set from the previously iteration. There is no such test
-!         in put_vars and put_varm.
-!
-!           err = nf90mpi_put_var_all(ncid, i, value, start, edge)
-!           if (canConvert) then
-!               if (err .ne. NF90_NOERR)  &
-!                   call error(nf90mpi_strerror(err))
-!           else
-!               if (err .ne. NF90_ECHAR) &
-!                   call errore('wrong type: ', err)
-!           endif
-
-            do 22, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 2
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nf90mpi_put_var_all(ncid, i, value, start, edge)
+            if (canConvert) then
+                if (err .ne. NF90_NOERR)  &
+                    call error(nf90mpi_strerror(err))
+            else
+                if (err .ne. NF90_ECHAR) &
+                    call errore('wrong type: ', err)
+            endif
+            do 6, j = 1, var_rank(i)
                 edge(j) = 1
-22          continue
-
+6           continue
 
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
             !/* bits of k determine whether to put lower or upper part of dim */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nels = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -796,22 +805,22 @@ define([TEST_NFMPI_PUT_VARA],dnl
                         edge(j) = var_shape(j,i) - mid(j)
                     end if
                     nels = nels * edge(j)
-6               continue
+9               continue
                 allInExtRange = .true.
-                do 7, j = 1, INT(nels)
+                do 10, j = 1, INT(nels)
                     err = index2indexes(j, var_rank(i), edge, index)
                     if (err .ne. NF90_NOERR)  &
                         call error('error in index2indexes 1')
-                    do 8, d = 1, var_rank(i)
+                    do 11, d = 1, var_rank(i)
                         index(d) = index(d) + start(d) - 1
-8                   continue
+11                  continue
                     val = hash_$1(var_type(i), var_rank(i), &
                                   index, NFT_ITYPE($1))
                     MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
                     val = ARITH3($1, value, j)
                     allInExtRange = allInExtRange .and. &
                         inRange3(val, var_type(i), NFT_ITYPE($1))
-7               continue
+10              continue
                 err = nf90mpi_put_var_all(ncid, i, value, start, edge)
                 if (canConvert) then
                     if (allInExtRange) then
@@ -825,7 +834,7 @@ define([TEST_NFMPI_PUT_VARA],dnl
                     if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
                         call errore('wrong type: ', err)
                 end if
-5           continue
+8           continue
 1       continue
 
         err = nf90mpi_close(ncid)
@@ -910,54 +919,101 @@ define([TEST_NFMPI_PUT_VARS],dnl
             if (err .ne. NF90_ENOTVAR)  &
                 call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    ! skip record dim
-                    start(j) = var_shape(j,i) + 1
-                    err = nf90mpi_put_var_all(ncid, i, value, start, &
-                                         edge, stride)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EINVALCOORDS) &
-                                call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nf90mpi_put_var_all(ncid, i, value, start, &
-                                         edge, stride)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EEDGE) &
-                            call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                    stride(j) = 0
-                    err = nf90mpi_put_var_all(ncid, i, value, start, &
-                                         edge, stride)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_ESTRIDE) &
-                            call errore('bad stride: ', err)
-                    endif
-                    stride(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_ESTRIDE) &
+                        call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
 3           continue
+
+!           /* Check correct error returned even when nothing to put */
+            do 4, j = 1, var_rank(i)
+                edge(j) = 0
+4           continue
+            err = nf90mpi_put_var_all(BAD_ID, i, value, start, edge, stride)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_put_var_all(ncid, BAD_VARID, value, start, edge, stride)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+#else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+#endif
+                endif
+                start(j) = var_shape(j,i) + 2
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nf90mpi_put_var_all(ncid, i, value, start, edge, stride)
+            if (canConvert) then
+                if (err .ne. NF90_NOERR)  &
+                    call error(nf90mpi_strerror(err))
+            else
+                if (err .ne. NF90_ECHAR) &
+                    call errore('wrong type: ', err)
+            endif
+            do 6, j = 1, var_rank(i)
+                edge(j) = 1
+6           continue
+
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
             !/* bits of k determine whether to put lower or upper part of dim */
             !/* choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -972,17 +1028,17 @@ define([TEST_NFMPI_PUT_VARS],dnl
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * stride(j)
-6               continue
-                do 7, m = 1, INT(nstarts)
+9               continue
+                do 10, m = 1, INT(nstarts)
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF90_NOERR) &
                         call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) / stride(j)
                         nels = nels * count(j)
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
                     !/* Random choice of forward or backward */
 ! TODO
 !                   if ( roll(2) ) {
@@ -993,15 +1049,15 @@ define([TEST_NFMPI_PUT_VARS],dnl
 !                   }
 !
                     allInExtRange = .true.
-                    do 9, j = 1, INT(nels)
+                    do 12, j = 1, INT(nels)
                         err = index2indexes(j, var_rank(i), count,  &
                                             index2)
                         if (err .ne. NF90_NOERR) &
                             call error('error in index2indexes')
-                        do 10, d = 1, var_rank(i)
+                        do 13, d = 1, var_rank(i)
                             index2(d) = index(d) +  &
                                         (index2(d)-1) * stride(d)
-10                      continue
+13                      continue
                         val = hash_$1(var_type(i), var_rank(i), &
                                       index2, NFT_ITYPE($1))
                         MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
@@ -1009,7 +1065,7 @@ define([TEST_NFMPI_PUT_VARS],dnl
                         allInExtRange = allInExtRange .and. &
                             inRange3(val, var_type(i),  &
                                      NFT_ITYPE($1))
-9                   continue
+12                  continue
                     err = nf90mpi_put_var_all(ncid, i, value, index, &
                                          count, stride)
                     if (canConvert) then
@@ -1024,8 +1080,8 @@ define([TEST_NFMPI_PUT_VARS],dnl
                         if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
                             call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 1       continue
 
         err = nf90mpi_close(ncid)
@@ -1112,58 +1168,108 @@ define([TEST_NFMPI_PUT_VARM],dnl
             if (err .ne. NF90_EBADID)  &
                 call errore('bad ncid: ', err)
             err = nf90mpi_put_var_all(ncid, BAD_VARID, value, start, &
-                                 edge, stride, imap)
+                                      edge, stride, imap)
             if (err .ne. NF90_ENOTVAR)  &
                 call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
-                    start(j) = var_shape(j,i) + 1
-                    err = nf90mpi_put_var_all(ncid, i, value, start, &
-                                         edge, stride, imap)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EINVALCOORDS) &
-                            call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nf90mpi_put_var_all(ncid, i, value, start, &
-                                         edge, stride, imap)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_EEDGE) &
-                            call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                    stride(j) = 0
-                    err = nf90mpi_put_var_all(ncid, i, value, start, &
-                                         edge, stride, imap)
-                    if (.not. canConvert) then
-                        if (err .ne. NF90_ECHAR) &
-                            call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF90_ESTRIDE) &
-                            call errore('bad stride: ', err)
-                    endif
-                    stride(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_put_var_all(ncid, i, value, start, &
+                                          edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_put_var_all(ncid, i, value, start, &
+                                          edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nf90mpi_put_var_all(ncid, i, value, start, &
+                                          edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_ESTRIDE) &
+                        call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
 3           continue
+
+!           /* Check correct error returned even when nothing to put */
+            do 4, j = 1, var_rank(i)
+                edge(j) = 0
+4           continue
+            err = nf90mpi_put_var_all(BAD_ID, i, value, start, edge, stride, imap)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_put_var_all(ncid, BAD_VARID, value, start, edge, stride, imap)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+#else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+#endif
+                endif
+                start(j) = var_shape(j,i) + 2
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nf90mpi_put_var_all(ncid, i, value, start, edge, stride, imap)
+            if (canConvert) then
+                if (err .ne. NF90_NOERR)  &
+                    call error(nf90mpi_strerror(err))
+            else
+                if (err .ne. NF90_ECHAR) &
+                    call errore('wrong type: ', err)
+            endif
+            do 6, j = 1, var_rank(i)
+                edge(j) = 1
+6           continue
+
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
             !/* bits of k determine whether to put lower or upper part of dim */
             !/* choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -1178,43 +1284,43 @@ define([TEST_NFMPI_PUT_VARM],dnl
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * stride(j)
-6               continue
-                do 7, m = 1, INT(nstarts)
+9               continue
+                do 10, m = 1, INT(nstarts)
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF90_NOERR) &
                         call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) / stride(j)
                         nels = nels * count(j)
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
                     !/* Random choice of forward or backward */
 ! TODO
 !                   if ( roll(2) ) then
-!                       do 9, j = 1, var_rank(i)
+!                       do 12, j = 1, var_rank(i)
 !                           index(j) = index(j) +  &
 !                               (count(j) - 1) * stride(j)
 !                           stride(j) = -stride(j)
-!9                      continue
+!12                     continue
 !                   end if
 !
                     if (var_rank(i) .gt. 0) then
                         imap(1) = 1
-                        do 10, j = 2, var_rank(i)
+                        do 13, j = 2, var_rank(i)
                             imap(j) = imap(j-1) * count(j-1)
-10                      continue
+13                      continue
                     end if
                     allInExtRange = .true.
-                    do 11 j = 1, INT(nels)
+                    do 14 j = 1, INT(nels)
                         err = index2indexes(j, var_rank(i), count,  &
                                             index2)
                         if (err .ne. NF90_NOERR) &
                             call error('error in index2indexes')
-                        do 12, d = 1, var_rank(i)
+                        do 15, d = 1, var_rank(i)
                             index2(d) = index(d) +  &
                                 (index2(d)-1) * stride(d)
-12                      continue
+15                      continue
                         val = hash_$1(var_type(i),var_rank(i), &
                                       index2, NFT_ITYPE($1))
                         MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
@@ -1222,7 +1328,7 @@ define([TEST_NFMPI_PUT_VARM],dnl
                         allInExtRange = allInExtRange .and. &
                             inRange3(val, var_type(i),  &
                                      NFT_ITYPE($1))
-11                  continue
+14                  continue
                     err = nf90mpi_put_var_all(ncid,i,value,index,count, &
                                          stride,imap)
                     if (canConvert) then
@@ -1237,8 +1343,8 @@ define([TEST_NFMPI_PUT_VARM],dnl
                         if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
                             call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 1       continue
 
         err = nf90mpi_close(ncid)
@@ -1340,16 +1446,7 @@ define([TEST_NFMPI_PUT_ATT],dnl
         end
 ])dnl
 
-divert(0)dnl
-dnl If you see this line, you can ignore the next one.
-! Do not edit this file. It is produced from the corresponding .m4 source */
-
-!
-!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
-!  See COPYRIGHT notice in top-level directory.
-!
-! $Id: test_put.m4 2156 2015-10-12 01:15:25Z wkliao $
-!
+dnl divert(0)dnl
 
 HASH(text)
 #ifdef NF_INT1_T
diff --git a/test/nf90_test/test_read.F90 b/test/nf90_test/test_read.F90
index aa6193f..4d3f7c3 100644
--- a/test/nf90_test/test_read.F90
+++ b/test/nf90_test/test_read.F90
@@ -2,7 +2,7 @@
 !  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: test_read.F90 2296 2016-01-06 21:19:36Z wkliao $
+! $Id: test_read.F90 2474 2016-09-05 23:13:05Z wkliao $
 !
 
 ! Test nf90mpi_strerror.
@@ -144,7 +144,10 @@
         if (err .eq. NF90_NOERR) then
             print*, &
         'opening a nonexistent file expects to fail, but got NF90_NOERR'
-        elseif (err .ne. NF90_ENOENT) then
+        elseif (err .ne. NF90_ENOENT .AND. err .ne. NF_EFILE) then
+!           older version of OpenMPI and MPICH may return MPI_ERR_IO instead
+!           of MPI_ERR_NO_SUCH_FILE */
+
             print*, &
         'opening a nonexistent file expects NF90_ENOENT, but got ',err
         else
diff --git a/test/nf_test/Makefile.in b/test/nf_test/Makefile.in
index 9b5c35d..98ecf73 100644
--- a/test/nf_test/Makefile.in
+++ b/test/nf_test/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+# $Id: Makefile.in 2614 2016-11-12 19:50:02Z wkliao $
 #
 # @configure_input@
 
@@ -16,6 +16,22 @@ INCLUDES += -I$(srcdir)/../../src/libf
 LDFLAGS  := $(LDFLAGS) -L../common
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
 
+ifeq (@HAVE_F77_GNU_INT@, yes)
+M4FLAGS += -DHAVE_F77_GNU_INT
+endif
+ifeq (@HAVE_F77_INT1@, yes)
+M4FLAGS += -DHAVE_F77_INT1
+endif
+ifeq (@HAVE_F77_INT2@, yes)
+M4FLAGS += -DHAVE_F77_INT2
+endif
+ifeq (@HAVE_F77_INT8@, yes)
+M4FLAGS += -DHAVE_F77_INT8
+endif
+ifeq (@RELAX_COORD_BOUND@, 1)
+FPPFLAGS := $(FPPFLAGS) @FC_DEFINE at RELAX_COORD_BOUND
+endif
+
 M4SRCS    = test_get.m4 \
             test_put.m4  \
             test_iget.m4 \
diff --git a/test/nf_test/test_get.m4 b/test/nf_test/test_get.m4
index fc5da7e..0e96a98 100644
--- a/test/nf_test/test_get.m4
+++ b/test/nf_test/test_get.m4
@@ -1,4 +1,18 @@
-divert(-1)
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl This file is supposed to be the same as PnetCDF's test_get.m4
+dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
+dnl
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_get.m4 2618 2016-11-14 22:47:18Z wkliao $
+
+dnl divert(-1)
 
 dnl This is m4 source.
 dnl Process using m4 to produce FORTRAN language file.
@@ -77,10 +91,10 @@ define([TEST_NFMPI_GET_VAR1],[dnl
         integer i
         integer j
         integer err
-        integer nok      
+        integer nok
         integer*8 index(MAX_RANK)
         doubleprecision expect
-        logical canConvert     
+        logical canConvert
         DATATYPE_VAR1($1, value)
         doubleprecision val
 
@@ -89,23 +103,22 @@ define([TEST_NFMPI_GET_VAR1],[dnl
         err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_open: ', err)
-        err = nfmpi_begin_indep_data(ncid)
         do 1, i = 1, numVars
             canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
             do 2, j = 1, var_rank(i)
                 index(j) = 1
 2           continue
-            err = nfmpi_get_var1_$1(BAD_ID, i, index, value)
+            err = nfmpi_get_var1_$1_all(BAD_ID, i, index, value)
             if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
-            err = nfmpi_get_var1_$1(ncid, BAD_VARID,
+            err = nfmpi_get_var1_$1_all(ncid, BAD_VARID,
      +                  index, value)
             if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
                 index(j) = var_shape(j,i) + 1
-                err = nfmpi_get_var1_$1(ncid, i, index, value)
+                err = nfmpi_get_var1_$1_all(ncid, i, index, value)
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -116,47 +129,44 @@ define([TEST_NFMPI_GET_VAR1],[dnl
                 index(j) = 1
 3           continue
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+                err = index2indexes(j, var_rank(i), var_shape(1,i),
      +                              index)
                 if (err .ne. NF_NOERR)
      +              call error('error in index2indexes 1')
-                expect = hash4( var_type(i), var_rank(i), index, 
-     +                          NFT_ITYPE($1) )
-                err = nfmpi_get_var1_$1(ncid, i, index,
+                expect = hash4(var_type(i), var_rank(i), index)
+                err = nfmpi_get_var1_$1_all(ncid, i, index,
      +                          value)
-                if (canConvert) then
-                    if (inRange3(expect,var_type(i), 
-     +                           NFT_ITYPE($1))) then
-                        if (in_internal_range(NFT_ITYPE($1),
-     +                                        expect)) then
-                            if (err .ne. NF_NOERR) then
-                                call errore('nfmpi_get_var1_$1: ',
-     +                                      err)
+                if (.NOT. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                    goto 4
+                endif
+                if (inRange3(expect,var_type(i),
+     +                       NFT_ITYPE($1))) then
+                    if (in_internal_range(NFT_ITYPE($1),
+     +                                    expect)) then
+                        if (err .ne. NF_NOERR) then
+                            call errore(
+     +                      'nfmpi_get_var1_$1_all: ', err)
+                        else
+                            val = ARITH_VAR1($1, value)
+                            if (.not. equal(val, expect, var_type(i),
+     +                                      NFT_ITYPE($1))) then
+                                call errori('varid: ', i)
+                                call errorc('var_name: ', var_name(i))
+                                call errord('unexpected: ', val)
+                                call errord('expecting: ', expect)
                             else
-                                val = ARITH_VAR1($1, value)
-                                if (.not. equal(val, expect, 
-     +                                          var_type(i), 
-     +                                          NFT_ITYPE($1))) then
-                                    call errori('varid: ', i)
-                                    call errorc('var_name: ',
-     +                                  var_name(i))
-                                    call errord('unexpected: ', val)
-                                    call errord('expecting: ', expect)
-                                else
-                                    nok = nok + 1
-                                end if
+                                nok = nok + 1
                             end if
-                        else
-                            if (err .ne. NF_ERANGE)
-     +                          call errore('Range error: ', err)
                         end if
                     else
-                        if (err .ne. NF_NOERR .and. err .ne. NF_ERANGE)
-     +                      call errore('OK or Range error: ', err)
+                        if (err .ne. NF_ERANGE)
+     +                      call errore('Range error: ', err)
                     end if
                 else
-                    if (err .ne. NF_ECHAR)
-     +                  call errore('wrong type: ', err)
+                    if (err .ne. NF_NOERR .and. err .ne. NF_ERANGE)
+     +                  call errore('OK or Range error: ', err)
                 end if
 4           continue
 1       continue
@@ -183,13 +193,13 @@ define([TEST_NFMPI_GET_VAR],[dnl
         integer i
         integer j
         integer err
-        logical allInExtRange   
-        logical allInIntRange   
+        logical allInExtRange
+        logical allInIntRange
         integer nels
-        integer nok      
+        integer nok
         integer*8 index(MAX_RANK)
         doubleprecision expect(MAX_NELS)
-        logical canConvert     
+        logical canConvert
         DATATYPE($1, value, (MAX_NELS))
         doubleprecision val
 
@@ -214,12 +224,11 @@ define([TEST_NFMPI_GET_VAR],[dnl
             allInExtRange = .true.
             allInIntRange = .true.
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+                err = index2indexes(j, var_rank(i), var_shape(1,i),
      +                              index)
                 if (err .ne. NF_NOERR)
      +              call error('error in index2indexes 1')
-                expect(j) = hash4( var_type(i), var_rank(i), index, 
-     +                          NFT_ITYPE($1) )
+                expect(j) = hash4(var_type(i), var_rank(i), index)
                 if (inRange3(expect(j),var_type(i), NFT_ITYPE($1))) then
                     allInIntRange = allInIntRange .and.
      +                  in_internal_range(NFT_ITYPE($1), expect(j))
@@ -231,7 +240,7 @@ define([TEST_NFMPI_GET_VAR],[dnl
             if (canConvert) then
                 if (allInExtRange) then
                     if (allInIntRange) then
-                        if (err .ne. NF_NOERR) 
+                        if (err .ne. NF_NOERR)
      +                      call errore('nfmpi_get_var_$1_all: ',
      +                                  err)
                     else
@@ -248,8 +257,8 @@ define([TEST_NFMPI_GET_VAR],[dnl
      +                  in_internal_range(NFT_ITYPE($1),
      +                                          expect(j))) then
                         val = ARITH3($1, value, j)
-                        if (.not. equal(val, expect(j), 
-     +                                  var_type(i), 
+                        if (.not. equal(val, expect(j),
+     +                                  var_type(i),
      +                                  NFT_ITYPE($1))) then
                             call errord('unexpected: ', val)
                             call errord('expecting: ', expect(j))
@@ -288,16 +297,16 @@ define([TEST_NFMPI_GET_VARA],[dnl
         integer j
         integer k
         integer err
-        logical allInExtRange   
-        logical allInIntRange   
+        logical allInExtRange
+        logical allInIntRange
         integer nels
         integer nslabs
-        integer nok      
+        integer nok
         integer*8 start(MAX_RANK)
         integer*8 edge(MAX_RANK)
         integer*8 index(MAX_RANK)
         integer*8 mid(MAX_RANK)
-        logical canConvert     
+        logical canConvert
         DATATYPE($1, value, (MAX_NELS))
         doubleprecision expect(MAX_NELS)
         doubleprecision val
@@ -309,7 +318,7 @@ define([TEST_NFMPI_GET_VARA],[dnl
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_open: ', err)
         do 1, i = 1, numVars
-            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
             if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
             if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
@@ -321,7 +330,7 @@ define([TEST_NFMPI_GET_VARA],[dnl
      +                  edge, value)
             if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
-            err = nfmpi_get_vara_$1_all(ncid, BAD_VARID, start, 
+            err = nfmpi_get_vara_$1_all(ncid, BAD_VARID, start,
      +                           edge, value)
             if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
@@ -343,52 +352,71 @@ define([TEST_NFMPI_GET_VARA],[dnl
 C           /* Check non-scalars for correct error returned even when */
 C           /* there is nothing to get (edge(j).eq.0) */
             if (var_rank(i) .gt. 0) then
-                do 10, j = 1, var_rank(i)
+                do 4, j = 1, var_rank(i)
                     edge(j) = 0
-10              continue
-                err = nfmpi_get_vara_$1_all(BAD_ID, i, start,
-     +                  edge, value)
-                if (err .ne. NF_EBADID) 
+4              continue
+                err = nfmpi_get_vara_$1_all(BAD_ID, i,
+     +                start, edge, value)
+                if (err .ne. NF_EBADID)
      +              call errore('bad ncid: ', err)
                 err = nfmpi_get_vara_$1_all(ncid, BAD_VARID,
-     +                  start, edge, value)
-                if (err .ne. NF_ENOTVAR) 
+     +                start, edge, value)
+                if (err .ne. NF_ENOTVAR)
      +              call errore('bad var id: ', err)
-                do 11, j = 1, var_rank(i)
-                    if (var_dimid(j,i) .gt. 1) then     !/* skip record dim */
-                        start(j) = var_shape(j,i) + 1
-                        err = nfmpi_get_vara_$1_all(ncid, i,
-     +                          start, edge, value)
-                        if (canConvert .and. err .ne. NF_EINVALCOORDS)
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_get_vara_$1_all(ncid, i,
+     +                    start, edge, value)
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .NE. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+#else
+                        if (err .NE. NF_EINVALCOORDS)
      +                      call errore('bad start: ', err)
-                        start(j) = 1
+#endif
                     endif
-11              continue
-                err = nfmpi_get_vara_$1_all(ncid, i, start,
-     +                          edge, value)
+                    start(j) = var_shape(j,i) + 2
+                    err = nfmpi_get_vara_$1_all(ncid, i,
+     +                    start, edge, value)
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+                        if (err .NE. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
+                err = nfmpi_get_vara_$1_all(ncid, i,
+     +                start, edge, value)
                 if (canConvert) then
-                    if (err .ne. NF_NOERR) 
+                    if (err .ne. NF_NOERR)
      +                  call error(nfmpi_strerror(err))
                 else
                     if (err .ne. NF_ECHAR)
      +                  call errore('wrong type: ', err)
                 endif
-                do 12, j = 1, var_rank(i)
+                do 6, j = 1, var_rank(i)
                     edge(j) = 1
-12              continue
+6               continue
             endif
 
 C           Choose a random point dividing each dim into 2 parts
 C           get 2^rank (nslabs) slabs so defined
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
-C           bits of k determine whether to get lower or upper part of dim 
-            do 5, k = 1, nslabs
+7           continue
+C           bits of k determine whether to get lower or upper part of dim
+            do 8, k = 1, nslabs
                 nels = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift((k-1), -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -397,27 +425,26 @@ C           bits of k determine whether to get lower or upper part of dim
                         edge(j) = var_shape(j,i) - mid(j)
                     end if
                     nels = nels * int(edge(j))
-6               continue
+9               continue
                 allInIntRange = .true.
                 allInExtRange = .true.
-                do 7, j = 1, nels
+                do 10, j = 1, nels
                     err = index2indexes(j, var_rank(i), edge, index)
                     if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes 1')
-                    do 8, d = 1, var_rank(i)
+                    do 11, d = 1, var_rank(i)
                         index(d) = index(d) + start(d) - 1
-8                   continue
-                    expect(j) = hash4(var_type(i), var_rank(i), index, 
-     +                                NFT_ITYPE($1))
-                    if (inRange3(expect(j),var_type(i), 
+11                  continue
+                    expect(j) = hash4(var_type(i), var_rank(i), index)
+                    if (inRange3(expect(j),var_type(i),
      +                           NFT_ITYPE($1))) then
-                        allInIntRange = 
+                        allInIntRange =
      +                      allInIntRange .and.
      +                      in_internal_range(NFT_ITYPE($1), expect(j))
                     else
                         allInExtRange = .false.
                     end if
-7               continue
+10              continue
                 err = nfmpi_get_vara_$1_all(ncid, i, start,
      +                          edge, value)
                 if (canConvert) then
@@ -434,14 +461,14 @@ C           bits of k determine whether to get lower or upper part of dim
                         if (err .ne. NF_NOERR .and. err .ne. NF_ERANGE)
      +                      call errore('OK or Range error: ', err)
                     end if
-                    do 9, j = 1, nels
+                    do 12, j = 1, nels
                         if (inRange3(expect(j),var_type(i),
      +                               NFT_ITYPE($1)) .and.
      +                      in_internal_range(NFT_ITYPE($1), expect(j)))
      +                          then
                             val = ARITH3($1, value, j)
                             if (.not.equal(val,expect(j),
-     +                                     var_type(i),NFT_ITYPE($1))) 
+     +                                     var_type(i),NFT_ITYPE($1)))
      +                              then
                                 call error(
      +                              'value read not that expected')
@@ -450,7 +477,7 @@ C           bits of k determine whether to get lower or upper part of dim
                                     call errori('varid: ', i)
                                     call errorc('var_name: ',
      +                                  var_name(i))
-                                    call errori('element number: %d ', 
+                                    call errori('element number: %d ',
      +                                          j)
                                     call errord('expect: ', expect(j))
                                     call errord('got: ', val)
@@ -459,12 +486,12 @@ C           bits of k determine whether to get lower or upper part of dim
                                 nok = nok + 1
                             end if
                         end if
-9                   continue
+12                  continue
                 else
                     if (nels .gt. 0  .and. err .ne. NF_ECHAR)
      +                  call errore('wrong type: ', err)
                 end if
-5           continue
+8           continue
 1       continue
         err = nfmpi_close(ncid)
         if (err .ne. NF_NOERR)
@@ -493,12 +520,12 @@ define([TEST_NFMPI_GET_VARS],dnl
         integer k
         integer m
         integer err
-        logical allInExtRange   
-        logical allInIntRange   
+        logical allInExtRange
+        logical allInIntRange
         integer nels
         integer nslabs
-        integer nstarts         
-        integer nok             
+        integer nstarts
+        integer nok
         integer*8 start(MAX_RANK)
         integer*8 edge(MAX_RANK)
         integer*8 index(MAX_RANK)
@@ -507,7 +534,7 @@ define([TEST_NFMPI_GET_VARS],dnl
         integer*8 count(MAX_RANK)
         integer*8 sstride(MAX_RANK)
         integer*8 stride(MAX_RANK)
-        logical canConvert     
+        logical canConvert
         DATATYPE($1, value, (MAX_NELS))
         doubleprecision expect(MAX_NELS)
         doubleprecision val
@@ -519,7 +546,7 @@ define([TEST_NFMPI_GET_VARS],dnl
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_open: ', err)
         do 1, i = 1, numVars
-            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
             if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
             if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
@@ -528,20 +555,18 @@ define([TEST_NFMPI_GET_VARS],dnl
                 edge(j) = 1
                 stride(j) = 1
 2           continue
-            err = nfmpi_get_vars_$1_all(BAD_ID, i, start,
-     +                  edge, stride, value)
+            err = nfmpi_get_vars_$1_all(BAD_ID, i,
+     +            start, edge, stride, value)
             if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
             err = nfmpi_get_vars_$1_all(ncid, BAD_VARID,
-     +                  start, edge, stride, 
-     +                           value)
+     +            start, edge, stride, value)
             if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
                 start(j) = var_shape(j,i) + 1
-                err = nfmpi_get_vars_$1_all(ncid, i, start,
-     +                               edge, stride, 
-     +                               value)
+                err = nfmpi_get_vars_$1_all(ncid, i,
+     +                start, edge, stride, value)
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -551,9 +576,8 @@ define([TEST_NFMPI_GET_VARS],dnl
                 endif
                 start(j) = 1
                 edge(j) = var_shape(j,i) + 1
-                err = nfmpi_get_vars_$1_all(ncid, i, start,
-     +                               edge, stride, 
-     +                               value)
+                err = nfmpi_get_vars_$1_all(ncid, i,
+     +                start, edge, stride, value)
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -563,8 +587,8 @@ define([TEST_NFMPI_GET_VARS],dnl
                 endif
                 edge(j) = 1
                 stride(j) = 0
-                err = nfmpi_get_vars_$1_all(ncid, i, start,
-     +                               edge, stride,value)
+                err = nfmpi_get_vars_$1_all(ncid, i,
+     +                start, edge, stride,value)
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -574,18 +598,76 @@ define([TEST_NFMPI_GET_VARS],dnl
                 endif
                 stride(j) = 1
 3           continue
+
+C           /* Check non-scalars for correct error returned even when */
+C           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 4, j = 1, var_rank(i)
+                    edge(j) = 0
+4               continue
+                err = nfmpi_get_vars_$1_all(BAD_ID, i,
+     +                start, edge, stride, value)
+                if (err .ne. NF_EBADID)
+     +              call errore('bad ncid: ', err)
+                err = nfmpi_get_vars_$1_all(ncid, BAD_VARID,
+     +                start, edge, stride, value)
+                if (err .ne. NF_ENOTVAR)
+     +              call errore('bad var id: ', err)
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_get_vars_$1_all(ncid, i,
+     +                    start, edge, stride, value)
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .NE. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+#else
+                        if (err .NE. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+#endif
+                    endif
+                    start(j) = var_shape(j,i) + 2
+                    err = nfmpi_get_vars_$1_all(ncid, i,
+     +                    start, edge, stride, value)
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+                        if (err .NE. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
+                err = nfmpi_get_vars_$1_all(ncid, i,
+     +                start, edge, stride, value)
+                if (canConvert) then
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                endif
+                do 6, j = 1, var_rank(i)
+                    edge(j) = 1
+6               continue
+            endif
+
 C           Choose a random point dividing each dim into 2 parts
 C           get 2^rank (nslabs) slabs so defined
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
 C           bits of k determine whether to get lower or upper part of dim
 C           choose random stride from 1 to edge
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, j-1), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -599,20 +681,20 @@ C           choose random stride from 1 to edge
                         sstride(j) = 1
                     end if
                     nstarts = nstarts * int(stride(j))
-6               continue
-                do 7, m = 1, nstarts
-                    err = index2indexes(m, var_rank(i), sstride, 
+9               continue
+                do 10, m = 1, nstarts
+                    err = index2indexes(m, var_rank(i), sstride,
      +                                  index)
                     if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
-                        count(j) = 1 + (edge(j) - index(j)) / 
+                    do 11, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) /
      +                                  stride(j)
                         nels = nels * int(count(j))
                         index(j) = index(j) + start(j) - 1
-8                   continue
-C                   Random choice of forward or backward 
+11                  continue
+C                   Random choice of forward or backward
 C    /* TODO
 C                   if ( roll(2) ) then
 C                       for (j = 0 j < var_rank(i) j++) {
@@ -623,27 +705,27 @@ C                   end if
 C    */
                     allInIntRange = .true.
                     allInExtRange = .true.
-                    do 9, j = 1, nels
-                        err = index2indexes(j, var_rank(i), count, 
+                    do 12, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count,
      +                                      index2)
                         if (err .ne. NF_NOERR)
      +                      call error('error in index2indexes() 1')
-                        do 10, d = 1, var_rank(i)
-                            index2(d) = index(d) + (index2(d)-1) * 
+                        do 13, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) *
      +                                  stride(d)
-10                      continue
-                        expect(j) = hash4(var_type(i), var_rank(i), 
-     +                                    index2, NFT_ITYPE($1))
+13                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i),
+     +                                    index2)
                         if (inRange3(expect(j),var_type(i),
      +                               NFT_ITYPE($1))) then
-                            allInIntRange = 
+                            allInIntRange =
      +                          allInIntRange .and.
-     +                          in_internal_range(NFT_ITYPE($1), 
+     +                          in_internal_range(NFT_ITYPE($1),
      +                                            expect(j))
                         else
                             allInExtRange = .false.
                         end if
-9                   continue
+12                  continue
                     err = nfmpi_get_vars_$1_all(ncid, i, index,
      +                                   count, stride,
      +                                   value)
@@ -661,10 +743,10 @@ C    */
      +                          err .ne. NF_ERANGE)
      +                          call errore('OK or Range error: ', err)
                         end if
-                        do 11, j = 1, nels
+                        do 14, j = 1, nels
                             if (inRange3(expect(j),var_type(i),
      +                          NFT_ITYPE($1)) .and.
-     +                          in_internal_range(NFT_ITYPE($1), 
+     +                          in_internal_range(NFT_ITYPE($1),
      +                                            expect(j))) then
                                 val = ARITH3($1, value, j)
                                 if (.not.equal(val, expect(j),
@@ -674,11 +756,11 @@ C    */
                                     if (verbose) then
                                         call error(' ')
                                         call errori('varid: ', i)
-                                        call errorc('var_name: ', 
+                                        call errorc('var_name: ',
      +                                              var_name(i))
                                         call errori('element number: ',
      +                                              j)
-                                        call errord('expect: ', 
+                                        call errord('expect: ',
      +                                              expect(j))
                                         call errord('got: ', val)
                                     end if
@@ -686,13 +768,13 @@ C    */
                                     nok = nok + 1
                                 end if
                             end if
-11                      continue
+14                      continue
                     else
                         if (nels .gt. 0 .and. err .ne. NF_ECHAR)
      +                      call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 
 1       continue
         err = nfmpi_close(ncid)
@@ -722,12 +804,12 @@ define([TEST_NFMPI_GET_VARM],dnl
         integer k
         integer m
         integer err
-        logical allInExtRange   
-        logical allInIntRange   
+        logical allInExtRange
+        logical allInIntRange
         integer nels
         integer nslabs
-        integer nstarts         
-        integer nok             
+        integer nstarts
+        integer nok
         integer*8 start(MAX_RANK)
         integer*8 edge(MAX_RANK)
         integer*8 index(MAX_RANK)
@@ -737,7 +819,7 @@ define([TEST_NFMPI_GET_VARM],dnl
         integer*8 sstride(MAX_RANK)
         integer*8 stride(MAX_RANK)
         integer*8 imap(MAX_RANK)
-        logical canConvert     
+        logical canConvert
         DATATYPE($1, value, (MAX_NELS))
         doubleprecision expect(MAX_NELS)
         doubleprecision val
@@ -749,7 +831,7 @@ define([TEST_NFMPI_GET_VARM],dnl
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_open: ', err)
         do 1, i = 1, numVars
-            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
             if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assertion'
             if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assertion'
@@ -760,19 +842,19 @@ define([TEST_NFMPI_GET_VARM],dnl
                 imap(j) = 1
 2           continue
             err = nfmpi_get_varm_$1_all(BAD_ID, i, start, edge,
-     +                           stride, imap, 
+     +                           stride, imap,
      +                           value)
             if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
             err = nfmpi_get_varm_$1_all(ncid, BAD_VARID, start,
-     +                           edge, stride, 
+     +                           edge, stride,
      +                           imap, value)
             if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
                 start(j) = var_shape(j,i) + 1
                 err = nfmpi_get_varm_$1_all(ncid, i, start,
-     +                               edge, stride, 
+     +                               edge, stride,
      +                               imap, value)
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
@@ -784,7 +866,7 @@ define([TEST_NFMPI_GET_VARM],dnl
                 start(j) = 1
                 edge(j) = var_shape(j,i) + 1
                 err = nfmpi_get_varm_$1_all(ncid, i, start,
-     +                               edge, stride, 
+     +                               edge, stride,
      +                               imap, value)
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
@@ -796,7 +878,7 @@ define([TEST_NFMPI_GET_VARM],dnl
                 edge(j) = 1
                 stride(j) = 0
                 err = nfmpi_get_varm_$1_all(ncid, i, start,
-     +                               edge, stride, 
+     +                               edge, stride,
      +                               imap, value)
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
@@ -807,19 +889,77 @@ define([TEST_NFMPI_GET_VARM],dnl
                 endif
                 stride(j) = 1
 3           continue
-C           Choose a random point dividing each dim into 2 parts 
-C           get 2^rank (nslabs) slabs so defined 
+
+C           /* Check non-scalars for correct error returned even when */
+C           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 4, j = 1, var_rank(i)
+                    edge(j) = 0
+4               continue
+                err = nfmpi_get_varm_$1_all(BAD_ID, i,
+     +                start, edge, stride, imap, value)
+                if (err .ne. NF_EBADID)
+     +              call errore('bad ncid: ', err)
+                err = nfmpi_get_varm_$1_all(ncid, BAD_VARID,
+     +                start, edge, stride, imap, value)
+                if (err .ne. NF_ENOTVAR)
+     +              call errore('bad var id: ', err)
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_get_varm_$1_all(ncid, i,
+     +                    start, edge, stride, imap, value)
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .NE. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+#else
+                        if (err .NE. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+#endif
+                    endif
+                    start(j) = var_shape(j,i) + 2
+                    err = nfmpi_get_varm_$1_all(ncid, i,
+     +                    start, edge, stride, imap, value)
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+                        if (err .NE. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
+                err = nfmpi_get_varm_$1_all(ncid, i,
+     +                start, edge, stride, imap, value)
+                if (canConvert) then
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                endif
+                do 6, j = 1, var_rank(i)
+                    edge(j) = 1
+6               continue
+            endif
+
+C           Choose a random point dividing each dim into 2 parts
+C           get 2^rank (nslabs) slabs so defined
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
-C           /* bits of k determine whether to get lower or upper part 
+7           continue
+C           /* bits of k determine whether to get lower or upper part
 C            * of dim
 C            * choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift((k-1), -(j-1)), 2) .ne. 0) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -834,19 +974,19 @@ C            * choose random stride from 1 to edge */
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * int(stride(j))
-6               continue
-                do 7, m = 1, nstarts
+9               continue
+                do 10, m = 1, nstarts
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
-                        count(j) = 1 + (edge(j) - index(j)) / 
+                    do 11, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) /
      +                                  stride(j)
                         nels = nels * int(count(j))
                         index(j) = index(j) + start(j) - 1
-8                   continue
-C                   Random choice of forward or backward 
+11                  continue
+C                   Random choice of forward or backward
 C    /* TODO
 C                   if ( roll(2) ) then
 C                       for (j = 0 j < var_rank(i) j++) {
@@ -857,82 +997,79 @@ C                   end if
 C     */
                     if (var_rank(i) .gt. 0) then
                         imap(1) = 1
-                        do 9, j = 2, var_rank(i)
+                        do 12, j = 2, var_rank(i)
                             imap(j) = imap(j-1) * count(j-1)
-9                       continue
+12                      continue
                     end if
                     allInIntRange = .true.
                     allInExtRange = .true.
-                    do 10, j = 1, nels
-                        err = index2indexes(j, var_rank(i), count, 
+                    do 13, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count,
      +                                      index2)
                         if (err .ne. NF_NOERR)
      +                      call error('error in index2indexes 1')
-                        do 11, d = 1, var_rank(i)
-                            index2(d) = index(d) + (index2(d)-1) * 
+                        do 14, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) *
      +                                  stride(d)
-11                      continue
-                        expect(j) = hash4(var_type(i), var_rank(i), 
-     +                                    index2, NFT_ITYPE($1))
+14                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i),
+     +                                    index2)
                         if (inRange3(expect(j),var_type(i),
      +                               NFT_ITYPE($1))) then
-                            allInIntRange = 
-     +                          allInIntRange .and.
+                            allInIntRange = allInIntRange .and.
      +                          in_internal_range(NFT_ITYPE($1),
      +                                            expect(j))
                         else
                             allInExtRange = .false.
                         end if
-10                  continue
-                    err = nfmpi_get_varm_$1_all(ncid,i,index,count,
-     +                                   stride,imap,value)
-                    if (canConvert) then
-                        if (allInExtRange) then
-                            if (allInIntRange) then
-                                if (err .ne. NF_NOERR)
-     +                              call error(nfmpi_strerror(err))
-                            else
-                                if (err .ne. NF_ERANGE)
-     +                              call errore('Range error: ', err)
-                            end if
+13                  continue
+                    err = nfmpi_get_varm_$1_all(ncid,i,
+     +                    index,count,stride,imap,value)
+                    if (.NOT. canConvert) then
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                        goto 10
+                    endif
+                    if (allInExtRange) then
+                        if (allInIntRange) then
+                            if (err .ne. NF_NOERR)
+     +                          call error(nfmpi_strerror(err))
                         else
-                            if (err .ne. NF_NOERR .and.
-     +                          err .ne. NF_ERANGE)
-     +                          call errore('OK or Range error: ', err)
+                            if (err .ne. NF_ERANGE)
+     +                          call errore('Range error: ', err)
                         end if
-                        do 12, j = 1, nels
-                            if (inRange3(expect(j),var_type(i),
-     +                                   NFT_ITYPE($1)) .and.
-     +                          in_internal_range(NFT_ITYPE($1),
-     +                                            expect(j))) then
-                                val = ARITH3($1, value, j)
-                                if (.not.equal(val, expect(j),
-     +                                         var_type(i), 
-     +                                         NFT_ITYPE($1))) then
-                                    call error(
-     +                                  'value read not that expected')
-                                    if (verbose) then
-                                        call error(' ')
-                                        call errori('varid: ', i)
-                                        call errorc('var_name: ', 
-     +                                          var_name(i))
-                                        call errori('element number: ',
-     +                                              j)
-                                        call errord('expect: ', 
-     +                                              expect(j))
-                                        call errord('got: ', val)
-                                    end if
-                                else
-                                    nok = nok + 1
-                                end if
-                            end if
-12                      continue
                     else
-                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
-     +                      call errore('wrong type: ', err)
+                        if (err .ne. NF_NOERR .and. err .ne. NF_ERANGE)
+     +                      call errore('OK or Range error: ', err)
                     end if
-7               continue
-5           continue
+                    do 15, j = 1, nels
+                        if (inRange3(expect(j),var_type(i),
+     +                               NFT_ITYPE($1)) .and.
+     +                      in_internal_range(NFT_ITYPE($1),
+     +                                        expect(j))) then
+                            val = ARITH3($1, value, j)
+                            if (.not.equal(val, expect(j), var_type(i),
+     +                                     NFT_ITYPE($1))) then
+                                call error(
+     +                              'value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('var_name: ',
+     +                                      var_name(i))
+                                    call errori('element number: ',
+     +                                          j)
+                                    call errord('expect: ',
+     +                                          expect(j))
+                                    call errord('got: ', val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+15                  continue
+10              continue
+8           continue
 1       continue
         err = nfmpi_close(ncid)
         if (err .ne. NF_NOERR)
@@ -963,16 +1100,16 @@ define([TEST_NFMPI_GET_ATT],dnl
         integer*8 ndx(1)
         logical allInExtRange
         logical allInIntRange
-        logical canConvert     
+        logical canConvert
         DATATYPE($1, value, (MAX_NELS))
         doubleprecision expect(MAX_NELS)
-        integer nok             
+        integer nok
         doubleprecision val
 
         nok = 0
 
         err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_open: ', err)
 
         do 1, i = 0, numVars
@@ -980,36 +1117,35 @@ define([TEST_NFMPI_GET_ATT],dnl
                 canConvert = (ATT_TYPE(j,i) .eq. NF_CHAR) .eqv.
      +                       (NFT_ITYPE($1) .eq. NFT_TEXT)
                 err = nfmpi_get_att_$1(BAD_ID, i,
-     +                  ATT_NAME(j,i), 
+     +                  ATT_NAME(j,i),
      +                  value)
-                if (err .ne. NF_EBADID) 
+                if (err .ne. NF_EBADID)
      +              call errore('bad ncid: ', err)
-                err = nfmpi_get_att_$1(ncid, BAD_VARID, 
-     +                              ATT_NAME(j,i), 
+                err = nfmpi_get_att_$1(ncid, BAD_VARID,
+     +                              ATT_NAME(j,i),
      +                              value)
-                if (err .ne. NF_ENOTVAR) 
+                if (err .ne. NF_ENOTVAR)
      +              call errore('bad var id: ', err)
                 err = nfmpi_get_att_$1(ncid, i,
-     +                                 'noSuch', 
+     +                                 'noSuch',
      +                                  value)
-                if (err .ne. NF_ENOTATT) 
+                if (err .ne. NF_ENOTATT)
      +              call errore('Bad attribute name: ', err)
                 allInIntRange = .true.
                 allInExtRange = .true.
                 do 3, k = 1, ATT_LEN(j,i)
                     ndx(1) = k
-                    expect(k) = hash4(ATT_TYPE(j,i), -1, ndx, 
-     +                                NFT_ITYPE($1))
+                    expect(k) = hash4(ATT_TYPE(j,i), -1, ndx)
                     if (inRange3(expect(k),ATT_TYPE(j,i),
      +                           NFT_ITYPE($1))) then
-                        allInIntRange = 
+                        allInIntRange =
      +                      allInIntRange .and.
      +                      in_internal_range(NFT_ITYPE($1), expect(k))
                     else
                         allInExtRange = .false.
                     end if
 3               continue
-                err = nfmpi_get_att_$1(ncid, i, 
+                err = nfmpi_get_att_$1(ncid, i,
      +                                 ATT_NAME(j,i),
      +                                 value)
                 if (canConvert .or. ATT_LEN(j,i) .eq. 0) then
@@ -1034,14 +1170,14 @@ define([TEST_NFMPI_GET_ATT],dnl
      +                                        expect(k))) then
                             val = ARITH3($1, value, k)
                             if (.not.equal(val, expect(k),
-     +                                     ATT_TYPE(j,i), 
+     +                                     ATT_TYPE(j,i),
      +                                     NFT_ITYPE($1)))then
                                 call error(
      +                              'value read not that expected')
                                 if (verbose) then
                                     call error(' ')
                                     call errori('varid: ', i)
-                                    call errorc('att_name: ', 
+                                    call errorc('att_name: ',
      +                                  ATT_NAME(j,i))
                                     call errori('element number: ', k)
                                     call errord('expect: ', expect(k))
@@ -1066,15 +1202,7 @@ define([TEST_NFMPI_GET_ATT],dnl
         end
 ])dnl
 
-divert(0)dnl
-dnl If you see this line, you can ignore the next one.
-C Do not edit this file. It is produced from the corresponding .m4 source */
-
-C*********************************************************************
-C   Copyright 1996, UCAR/Unidata
-C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
-C   $Id: test_get.m4 2224 2015-12-16 06:10:36Z wkliao $
-C*********************************************************************
+dnl divert(0)dnl
 
 TEST_NFMPI_GET_VAR1(text)
 #ifdef NF_INT1_T
diff --git a/test/nf_test/test_iget.m4 b/test/nf_test/test_iget.m4
index db913f1..8f96e69 100644
--- a/test/nf_test/test_iget.m4
+++ b/test/nf_test/test_iget.m4
@@ -1,4 +1,18 @@
-divert(-1)
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl This file is supposed to be the same as PnetCDF's test_iget.m4
+dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
+dnl
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_iget.m4 2618 2016-11-14 22:47:18Z wkliao $
+
+dnl divert(-1)
 
 dnl This is m4 source.
 dnl Process using m4 to produce FORTRAN language file.
@@ -77,10 +91,10 @@ define([TEST_NFMPI_IGET_VAR1],[dnl
         integer i
         integer j
         integer err
-        integer nok      
+        integer nok
         integer*8 index(MAX_RANK)
         doubleprecision expect
-        logical canConvert     
+        logical canConvert
         DATATYPE_VAR1($1, value)
         doubleprecision val
         integer err_w, reqid(1), st(1)
@@ -108,8 +122,6 @@ define([TEST_NFMPI_IGET_VAR1],[dnl
                 index(j) = var_shape(j,i) + 1
                 err = nfmpi_iget_var1_$1(ncid,i,index,value,
      +                               reqid(1))
-                if (err .eq. NF_NOERR)
-     +              err_w = nfmpi_wait_all(ncid, 1, reqid, st)
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -120,44 +132,43 @@ define([TEST_NFMPI_IGET_VAR1],[dnl
                 index(j) = 1
 3           continue
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+                err = index2indexes(j, var_rank(i), var_shape(1,i),
      +                              index)
                 if (err .ne. NF_NOERR)
      +              call error('error in index2indexes 1')
-                expect = hash4( var_type(i), var_rank(i), index, 
-     +                          NFT_ITYPE($1) )
+                expect = hash4(var_type(i), var_rank(i), index)
                 err = nfmpi_iget_var1_$1(ncid,i,index,value,
      +                               reqid(1))
                 if (err .eq. NF_NOERR)
      +              err_w = nfmpi_wait_all(ncid, 1, reqid, st)
-                if (canConvert) then
-                    if (inRange3(expect,var_type(i), 
-     +                           NFT_ITYPE($1))) then
-                        if (in_internal_range(NFT_ITYPE($1),
-     +                                        expect)) then
-                            if (st(1) .ne. 0) then
-                                call errore('nfmpi_iget_var: ',st(1))
+                if (.NOT. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                    goto 4
+                end if
+                if (inRange3(expect,var_type(i),
+     +                       NFT_ITYPE($1))) then
+                    if (in_internal_range(NFT_ITYPE($1),
+     +                                    expect)) then
+                        if (st(1) .ne. 0) then
+                            call errore('nfmpi_iget_var: ',st(1))
+                        else
+                            val = ARITH_VAR1($1, value)
+                            if (.not. equal(val, expect,
+     +                                      var_type(i),
+     +                                      NFT_ITYPE($1))) then
+                                call errord('unexpected: ', val)
                             else
-                                val = ARITH_VAR1($1, value)
-                                if (.not. equal(val, expect, 
-     +                                          var_type(i), 
-     +                                          NFT_ITYPE($1))) then
-                                    call errord('unexpected: ', val)
-                                else
-                                    nok = nok + 1
-                                end if
+                                nok = nok + 1
                             end if
-                        else
-                            if (st(1) .ne. NF_ERANGE)
-     +                          call errore('Range error: ', st(1))
                         end if
                     else
-                        if (st(1) .ne. 0  .and. st(1) .ne. NF_ERANGE)
-     +                      call errore('OK or Range error: ', st(1))
+                        if (st(1) .ne. NF_ERANGE)
+     +                      call errore('Range error: ', st(1))
                     end if
                 else
-                    if (err .ne. NF_ECHAR)
-     +                  call errore('wrong type: ', err)
+                    if (st(1) .ne. 0  .and. st(1) .ne. NF_ERANGE)
+     +                  call errore('OK or Range error: ', st(1))
                 end if
 4           continue
 1       continue
@@ -183,16 +194,16 @@ define([TEST_NFMPI_IGET_VAR],[dnl
         integer i
         integer j
         integer err
-        logical allInExtRange   
-        logical allInIntRange   
+        logical allInExtRange
+        logical allInIntRange
         integer nels
-        integer nok      
+        integer nok
         integer*8 index(MAX_RANK)
         doubleprecision expect(MAX_NELS)
-        logical canConvert     
+        logical canConvert
         DATATYPE($1, value, (MAX_NELS))
         doubleprecision val
-        integer err_w, reqid(1), st(1)      
+        integer err_w, reqid(1), st(1)
 
         nok = 0
 
@@ -215,12 +226,11 @@ define([TEST_NFMPI_IGET_VAR],[dnl
             allInExtRange = .true.
             allInIntRange = .true.
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+                err = index2indexes(j, var_rank(i), var_shape(1,i),
      +                              index)
                 if (err .ne. NF_NOERR)
      +              call error('error in index2indexes 1')
-                expect(j) = hash4( var_type(i), var_rank(i), index, 
-     +                          NFT_ITYPE($1) )
+                expect(j) = hash4(var_type(i), var_rank(i), index)
                 if (inRange3(expect(j),var_type(i), NFT_ITYPE($1))) then
                     allInIntRange = allInIntRange .and.
      +                  in_internal_range(NFT_ITYPE($1), expect(j))
@@ -231,38 +241,37 @@ define([TEST_NFMPI_IGET_VAR],[dnl
             err = nfmpi_iget_var_$1(ncid, i, value,reqid(1))
             if (err .eq. NF_NOERR)
      +          err_w = nfmpi_wait_all(ncid,1,reqid,st)
-            if (canConvert) then
-                if (allInExtRange) then
-                    if (allInIntRange) then
-                        if (st(1) .ne. 0) 
-     +                      call errore('nfmpi_iget_var: ', st(1))
-                    else
-                        if (st(1) .ne. NF_ERANGE)
-     +                      call errore('Range error: ', st(1))
-                    endif
+            if (.NOT. canConvert) then
+                if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                goto 1
+            end if
+            if (allInExtRange) then
+                if (allInIntRange) then
+                    if (st(1) .ne. 0)
+     +                  call errore('nfmpi_iget_var: ', st(1))
                 else
-                    if (st(1) .ne. 0  .and. st(1) .ne. NF_ERANGE)
+                    if (st(1) .ne. NF_ERANGE)
      +                  call errore('Range error: ', st(1))
                 endif
-                do 5, j = 1, var_nels(i)
-                    if (inRange3(expect(j),var_type(i),
-     +                           NFT_ITYPE($1)) .and.
-     +                  in_internal_range(NFT_ITYPE($1),
-     +                                          expect(j))) then
-                        val = ARITH3($1, value, j)
-                        if (.not. equal(val, expect(j), 
-     +                                  var_type(i), 
-     +                                  NFT_ITYPE($1))) then
-                            call errord('unexpected: ', val)
-                        else
-                            nok = nok + 1
-                        end if
-                    endif
-5               continue
             else
-                if (err .ne. NF_ECHAR)
-     +                  call errore('wrong type: ', err)
-            end if
+                if (st(1) .ne. 0  .and. st(1) .ne. NF_ERANGE)
+     +              call errore('Range error: ', st(1))
+            endif
+            do 5, j = 1, var_nels(i)
+                if (inRange3(expect(j),var_type(i),
+     +                       NFT_ITYPE($1)) .and.
+     +              in_internal_range(NFT_ITYPE($1),
+     +                                      expect(j))) then
+                    val = ARITH3($1, value, j)
+                    if (.not. equal(val, expect(j), var_type(i),
+     +                              NFT_ITYPE($1))) then
+                        call errord('unexpected: ', val)
+                    else
+                        nok = nok + 1
+                    end if
+                endif
+5           continue
 1       continue
         err = nfmpi_close(ncid)
         if (err .ne. NF_NOERR)
@@ -289,21 +298,21 @@ define([TEST_NFMPI_IGET_VARA],[dnl
         integer j
         integer k
         integer err
-        logical allInExtRange   
-        logical allInIntRange   
+        logical allInExtRange
+        logical allInIntRange
         integer nels
         integer nslabs
-        integer nok      
+        integer nok
         integer*8 start(MAX_RANK)
         integer*8 edge(MAX_RANK)
         integer*8 index(MAX_RANK)
         integer*8 mid(MAX_RANK)
-        logical canConvert     
+        logical canConvert
         DATATYPE($1, value, (MAX_NELS))
         doubleprecision expect(MAX_NELS)
         doubleprecision val
         integer ud_shift
-        integer err_w, reqid(1), st(1)      
+        integer err_w, reqid(1), st(1)
 
         nok = 0
 
@@ -311,7 +320,7 @@ define([TEST_NFMPI_IGET_VARA],[dnl
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_open: ', err)
         do 1, i = 1, numVars
-            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
             if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
             if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
@@ -319,87 +328,107 @@ define([TEST_NFMPI_IGET_VARA],[dnl
                 start(j) = 1
                 edge(j) = 1
 2           continue
-            err = nfmpi_iget_vara_$1(BAD_ID, i, start,
-     +                  edge, value,reqid(1))
+            err = nfmpi_iget_vara_$1(BAD_ID, i,
+     +            start, edge, value,reqid(1))
             if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
-            err = nfmpi_iget_vara_$1(ncid, BAD_VARID, start, 
-     +                           edge, value,reqid(1))
+            err = nfmpi_iget_vara_$1(ncid, BAD_VARID,
+     +            start,  edge, value,reqid(1))
             if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
                 start(j) = var_shape(j,i) + 1
-                err = nfmpi_iget_vara_$1(ncid, i, start,
-     +                               edge, value,reqid(1))
-                if (canConvert .and. err .ne. NF_EINVALCOORDS)
-     +              call errore('bad index: ', err)
-                if (err .EQ. NF_NOERR)
-     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                err = nfmpi_iget_vara_$1(ncid, i,
+     +                start, edge, value,reqid(1))
+                if (.NOT. canConvert) then
+                    if (err .NE. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad index: ', err)
+                endif
                 start(j) = 1
                 edge(j) = var_shape(j,i) + 1
-                err = nfmpi_iget_vara_$1(ncid, i, start,
-     +                               edge, value,reqid(1))
-                if (canConvert .and. err .ne. NF_EEDGE)
-     +              call errore('bad edge: ', err)
-                if (err .EQ. NF_NOERR)
-     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                err = nfmpi_iget_vara_$1(ncid, i,
+     +                start, edge, value,reqid(1))
+                if (.NOT. canConvert) then
+                    if (err .NE. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
                 edge(j) = 1
 3           continue
 
 C           /* Check non-scalars for correct error returned even when */
 C           /* there is nothing to get (edge(j).eq.0) */
             if (var_rank(i) .gt. 0) then
-                do 10, j = 1, var_rank(i)
+                do 4, j = 1, var_rank(i)
                     edge(j) = 0
-10              continue
-                err = nfmpi_iget_vara_$1(BAD_ID, i, start,
-     +                  edge, value,reqid(1))
-                if (err .ne. NF_EBADID) 
+4               continue
+                err = nfmpi_iget_vara_$1(BAD_ID, i,
+     +                start, edge, value,reqid(1))
+                if (err .ne. NF_EBADID)
      +              call errore('bad ncid: ', err)
                 err = nfmpi_iget_vara_$1(ncid, BAD_VARID,
-     +                  start, edge, value,reqid(1))
-                if (err .ne. NF_ENOTVAR) 
+     +                start, edge, value,reqid(1))
+                if (err .ne. NF_ENOTVAR)
      +              call errore('bad var id: ', err)
-                do 11, j = 1, var_rank(i)
-                    if (var_dimid(j,i) .gt. 1) then     !/* skip record dim */
-                        start(j) = var_shape(j,i) + 1
-                        err = nfmpi_iget_vara_$1(ncid, i,
-     +                          start, edge, value,reqid(1))
-                        if (canConvert .and. err .ne. NF_EINVALCOORDS)
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_iget_vara_$1(ncid, i,
+     +                    start, edge, value,reqid(1))
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .ne. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+#else
+                        if (err .ne. NF_EINVALCOORDS)
      +                      call errore('bad start: ', err)
-                        if (err .EQ. NF_NOERR)
-     +                      err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                        start(j) = 1
+#endif
                     endif
-11              continue
-                err = nfmpi_iget_vara_$1(ncid, i, start,
-     +                          edge, value,reqid(1))
-                if (err .EQ. NF_NOERR)
-     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                if (canConvert) then
-                    if (err .ne. NF_NOERR) then
-                        call error(nfmpi_strerror(err))
+                    start(j) = var_shape(j,i) + 2
+                    err = nfmpi_iget_vara_$1(ncid, i,
+     +                    start, edge, value,reqid(1))
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
                     endif
+                    start(j) = 1
+5               continue
+                err = nfmpi_iget_vara_$1(ncid, i,
+     +                start, edge, value,reqid(1))
+                if (canConvert) then
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
                 else
                     if (err .ne. NF_ECHAR)
      +                  call errore('wrong type: ', err)
                 endif
-                do 12, j = 1, var_rank(i)
+                do 6, j = 1, var_rank(i)
                     edge(j) = 1
-12              continue
+6               continue
             endif
 
 C           Choose a random point dividing each dim into 2 parts
 C           get 2^rank (nslabs) slabs so defined
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
-C           bits of k determine whether to get lower or upper part of dim 
-            do 5, k = 1, nslabs
+7           continue
+C           bits of k determine whether to get lower or upper part of dim
+            do 8, k = 1, nslabs
                 nels = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift((k-1), -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -408,76 +437,71 @@ C           bits of k determine whether to get lower or upper part of dim
                         edge(j) = var_shape(j,i) - mid(j)
                     end if
                     nels = nels * int(edge(j))
-6               continue
+9               continue
                 allInIntRange = .true.
                 allInExtRange = .true.
-                do 7, j = 1, nels
+                do 10, j = 1, nels
                     err = index2indexes(j, var_rank(i), edge, index)
                     if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes 1')
-                    do 8, d = 1, var_rank(i)
+                    do 11, d = 1, var_rank(i)
                         index(d) = index(d) + start(d) - 1
-8                   continue
-                    expect(j) = hash4(var_type(i), var_rank(i), index, 
-     +                                NFT_ITYPE($1))
-                    if (inRange3(expect(j),var_type(i), 
+11                  continue
+                    expect(j) = hash4(var_type(i), var_rank(i), index)
+                    if (inRange3(expect(j),var_type(i),
      +                           NFT_ITYPE($1))) then
-                        allInIntRange = 
+                        allInIntRange =
      +                      allInIntRange .and.
      +                      in_internal_range(NFT_ITYPE($1), expect(j))
                     else
                         allInExtRange = .false.
                     end if
-7               continue
+10              continue
                 err = nfmpi_iget_vara_$1(ncid, i, start,
      +                          edge, value,reqid(1))
                 if (err .EQ. NF_NOERR)
      +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                if (canConvert) then
-                    if (allInExtRange) then
-                        if (allInIntRange) then
-                            if (st(1) .ne. 0)
-     +                          call errore(
-     +                              'nfmpi_iget_vara_$1:',st(1))
-                        else
-                            if (st(1) .ne. NF_ERANGE)
-     +                          call errore('Range error: ', st(1))
-                        end if
+                if (.NOT. canConvert) then
+                    if (nels .gt. 0  .and. err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                    goto 8
+                end if
+                if (allInExtRange) then
+                    if (allInIntRange) then
+                        if (st(1) .ne. 0) call errore(
+     +                          'nfmpi_iget_vara_$1:',st(1))
                     else
-                        if (st(1) .ne. 0 .and. st(1) .ne. NF_ERANGE)
-     +                      call errore('OK or Range error: ', st(1))
+                        if (st(1) .ne. NF_ERANGE)
+     +                      call errore('Range error: ', st(1))
                     end if
-                    do 9, j = 1, nels
-                        if (inRange3(expect(j),var_type(i),
-     +                               NFT_ITYPE($1)) .and.
-     +                      in_internal_range(NFT_ITYPE($1), expect(j)))
+                else
+                    if (st(1) .ne. 0 .and. st(1) .ne. NF_ERANGE)
+     +                  call errore('OK or Range error: ', st(1))
+                end if
+                do 12, j = 1, nels
+                    if (inRange3(expect(j),var_type(i),
+     +                           NFT_ITYPE($1)) .and.
+     +                  in_internal_range(NFT_ITYPE($1), expect(j)))
+     +                      then
+                        val = ARITH3($1, value, j)
+                        if (.not.equal(val,expect(j),
+     +                                 var_type(i),NFT_ITYPE($1)))
      +                          then
-                            val = ARITH3($1, value, j)
-                            if (.not.equal(val,expect(j),
-     +                                     var_type(i),NFT_ITYPE($1))) 
-     +                              then
-                                call error(
-     +                              'value read not that expected')
-                                if (verbose) then
-                                    call error(' ')
-                                    call errori('varid: ', i)
-                                    call errorc('var_name: ',
-     +                                  var_name(i))
-                                    call errori('element number: %d ', 
-     +                                          j)
-                                    call errord('expect: ', expect(j))
-                                    call errord('got: ', val)
-                                end if
-                            else
-                                nok = nok + 1
+                            call error('value read not that expected')
+                            if (verbose) then
+                                call error(' ')
+                                call errori('varid: ', i)
+                                call errorc('var_name: ', var_name(i))
+                                call errori('element number: %d ', j)
+                                call errord('expect: ', expect(j))
+                                call errord('got: ', val)
                             end if
+                        else
+                            nok = nok + 1
                         end if
-9                   continue
-                else
-                    if (nels .gt. 0  .and. err .ne. NF_ECHAR)
-     +                  call errore('wrong type: ', err)
-                end if
-5           continue
+                    end if
+12              continue
+8           continue
 1       continue
         err = nfmpi_close(ncid)
         if (err .ne. NF_NOERR)
@@ -506,12 +530,12 @@ define([TEST_NFMPI_IGET_VARS],dnl
         integer k
         integer m
         integer err
-        logical allInExtRange   
-        logical allInIntRange   
+        logical allInExtRange
+        logical allInIntRange
         integer nels
         integer nslabs
-        integer nstarts         
-        integer nok             
+        integer nstarts
+        integer nok
         integer*8 start(MAX_RANK)
         integer*8 edge(MAX_RANK)
         integer*8 index(MAX_RANK)
@@ -520,12 +544,12 @@ define([TEST_NFMPI_IGET_VARS],dnl
         integer*8 count(MAX_RANK)
         integer*8 sstride(MAX_RANK)
         integer*8 stride(MAX_RANK)
-        logical canConvert     
+        logical canConvert
         DATATYPE($1, value, (MAX_NELS))
         doubleprecision expect(MAX_NELS)
         doubleprecision val
         integer ud_shift
-        integer err_w, reqid(1), st(1)      
+        integer err_w, reqid(1), st(1)
 
         nok = 0
 
@@ -533,7 +557,7 @@ define([TEST_NFMPI_IGET_VARS],dnl
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_open: ', err)
         do 1, i = 1, numVars
-            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
             if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
             if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
@@ -542,20 +566,18 @@ define([TEST_NFMPI_IGET_VARS],dnl
                 edge(j) = 1
                 stride(j) = 1
 2           continue
-            err = nfmpi_iget_vars_$1(BAD_ID, i, start,
-     +                  edge, stride, value,reqid(1))
+            err = nfmpi_iget_vars_$1(BAD_ID, i,
+     +            start, edge, stride, value,reqid(1))
             if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
             err = nfmpi_iget_vars_$1(ncid, BAD_VARID,
-     +                  start, edge, stride, value,reqid(1))
+     +            start, edge, stride, value,reqid(1))
             if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
                 start(j) = var_shape(j,i) + 1
-                err = nfmpi_iget_vars_$1(ncid, i, start, edge,
-     +                                    stride,value,reqid(1))
-                if (err .EQ. NF_NOERR)
-     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                err = nfmpi_iget_vars_$1(ncid, i,
+     +                start, edge, stride,value,reqid(1))
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -565,10 +587,8 @@ define([TEST_NFMPI_IGET_VARS],dnl
                 endif
                 start(j) = 1
                 edge(j) = var_shape(j,i) + 1
-                err = nfmpi_iget_vars_$1(ncid, i, start, edge,
-     +                               stride,value,reqid(1))
-                if (err .EQ. NF_NOERR)
-     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                err = nfmpi_iget_vars_$1(ncid, i,
+     +                start, edge, stride,value,reqid(1))
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -578,10 +598,8 @@ define([TEST_NFMPI_IGET_VARS],dnl
                 endif
                 edge(j) = 1
                 stride(j) = 0
-                err = nfmpi_iget_vars_$1(ncid, i, start, edge,
-     +                                stride,value,reqid(1))
-                if (err .EQ. NF_NOERR)
-     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                err = nfmpi_iget_vars_$1(ncid, i,
+     +                start, edge, stride,value,reqid(1))
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -591,18 +609,76 @@ define([TEST_NFMPI_IGET_VARS],dnl
                 endif
                 stride(j) = 1
 3           continue
-C               Choose a random point dividing each dim into 2 parts
-C               get 2^rank (nslabs) slabs so defined
+
+C           /* Check non-scalars for correct error returned even when */
+C           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 4, j = 1, var_rank(i)
+                    edge(j) = 0
+4               continue
+                err = nfmpi_iget_vars_$1(BAD_ID, i,
+     +                start, edge, stride, value,reqid(1))
+                if (err .ne. NF_EBADID)
+     +              call errore('bad ncid: ', err)
+                err = nfmpi_iget_vars_$1(ncid, BAD_VARID,
+     +                start, edge, stride, value,reqid(1))
+                if (err .ne. NF_ENOTVAR)
+     +              call errore('bad var id: ', err)
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_iget_vars_$1(ncid, i,
+     +                    start, edge, stride, value,reqid(1))
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .ne. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+#else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+#endif
+                    endif
+                    start(j) = var_shape(j,i) + 2
+                    err = nfmpi_iget_vars_$1(ncid, i,
+     +                    start, edge, stride, value,reqid(1))
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
+                err = nfmpi_iget_vars_$1(ncid, i,
+     +                start, edge, stride, value,reqid(1))
+                if (canConvert) then
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                endif
+                do 6, j = 1, var_rank(i)
+                    edge(j) = 1
+6               continue
+            endif
+
+C           Choose a random point dividing each dim into 2 parts
+C           get 2^rank (nslabs) slabs so defined
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
 C           bits of k determine whether to get lower or upper part of dim
 C           choose random stride from 1 to edge
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, j-1), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -616,20 +692,20 @@ C           choose random stride from 1 to edge
                         sstride(j) = 1
                     end if
                     nstarts = nstarts * int(stride(j))
-6               continue
-                do 7, m = 1, nstarts
-                    err = index2indexes(m, var_rank(i), sstride, 
+9               continue
+                do 10, m = 1, nstarts
+                    err = index2indexes(m, var_rank(i), sstride,
      +                                  index)
                     if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
-                        count(j) = 1 + (edge(j) - index(j)) / 
+                    do 11, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) /
      +                                  stride(j)
                         nels = nels * int(count(j))
                         index(j) = index(j) + start(j) - 1
-8                   continue
-C                   Random choice of forward or backward 
+11                  continue
+C                   Random choice of forward or backward
 C    /* TODO
 C                   if ( roll(2) ) then
 C                       for (j = 0 j < var_rank(i) j++) {
@@ -640,76 +716,74 @@ C                   end if
 C    */
                     allInIntRange = .true.
                     allInExtRange = .true.
-                    do 9, j = 1, nels
-                        err = index2indexes(j, var_rank(i), count, 
+                    do 12, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count,
      +                                      index2)
                         if (err .ne. NF_NOERR)
      +                      call error('error in index2indexes() 1')
-                        do 10, d = 1, var_rank(i)
-                            index2(d) = index(d) + (index2(d)-1) * 
+                        do 13, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) *
      +                                  stride(d)
-10                      continue
-                        expect(j) = hash4(var_type(i), var_rank(i), 
-     +                                    index2, NFT_ITYPE($1))
+13                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i),
+     +                                    index2)
                         if (inRange3(expect(j),var_type(i),
      +                               NFT_ITYPE($1))) then
-                            allInIntRange = 
+                            allInIntRange =
      +                          allInIntRange .and.
-     +                          in_internal_range(NFT_ITYPE($1), 
+     +                          in_internal_range(NFT_ITYPE($1),
      +                                            expect(j))
                         else
                             allInExtRange = .false.
                         end if
-9                   continue
+12                  continue
                     err = nfmpi_iget_vars_$1(ncid, i, index,
      +                                    count,stride,value,reqid(1))
                     if (err .EQ. NF_NOERR)
      +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                    if (canConvert) then
-                        if (allInExtRange) then
-                            if (allInIntRange) then
-                                if (st(1) .ne. 0)
-     +                              call error(nfmpi_strerror(st(1)))
-                            else
-                                if (st(1) .ne. NF_ERANGE)
-     +                              call errore('Range error: ', st(1))
-                            end if
+                    if (.NOT. canConvert) then
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                        goto 10
+                    end if
+                    if (allInExtRange) then
+                        if (allInIntRange) then
+                            if (st(1) .ne. 0)
+     +                          call error(nfmpi_strerror(st(1)))
                         else
-                            if (st(1) .ne. 0 .and. st(1) .ne. NF_ERANGE)
-     +                          call errore('OK or Range error: ',st(1))
+                            if (st(1) .ne. NF_ERANGE)
+     +                          call errore('Range error: ', st(1))
                         end if
-                        do 11, j = 1, nels
-                            if (inRange3(expect(j),var_type(i),
-     +                          NFT_ITYPE($1)) .and.
-     +                          in_internal_range(NFT_ITYPE($1), 
-     +                                            expect(j))) then
-                                val = ARITH3($1, value, j)
-                                if (.not.equal(val, expect(j),
-     +                              var_type(i), NFT_ITYPE($1))) then
-                                    call error(
-     +                                  'value read not that expected')
-                                    if (verbose) then
-                                        call error(' ')
-                                        call errori('varid: ', i)
-                                        call errorc('var_name: ', 
-     +                                              var_name(i))
-                                        call errori('element number: ',
-     +                                              j)
-                                        call errord('expect: ', 
-     +                                              expect(j))
-                                        call errord('got: ', val)
-                                    end if
-                                else
-                                    nok = nok + 1
-                                end if
-                            end if
-11                      continue
                     else
-                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
-     +                      call errore('wrong type: ', err)
+                        if (st(1) .ne. 0 .and. st(1) .ne. NF_ERANGE)
+     +                      call errore('OK or Range error: ',st(1))
                     end if
-7               continue
-5           continue
+                    do 14, j = 1, nels
+                        if (inRange3(expect(j),var_type(i),
+     +                      NFT_ITYPE($1)) .and.
+     +                      in_internal_range(NFT_ITYPE($1),
+     +                                        expect(j))) then
+                            val = ARITH3($1, value, j)
+                            if (.not.equal(val, expect(j),
+     +                          var_type(i), NFT_ITYPE($1))) then
+                                call error(
+     +                          'value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('var_name: ',
+     +                                          var_name(i))
+                                    call errori('element number: ',j)
+                                    call errord('expect: ',expect(j))
+                                    call errord('got: ', val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+14                  continue
+10               continue
+8           continue
 
 1       continue
         err = nfmpi_close(ncid)
@@ -739,12 +813,12 @@ define([TEST_NFMPI_IGET_VARM],dnl
         integer k
         integer m
         integer err
-        logical allInExtRange   
-        logical allInIntRange   
+        logical allInExtRange
+        logical allInIntRange
         integer nels
         integer nslabs
-        integer nstarts         
-        integer nok             
+        integer nstarts
+        integer nok
         integer*8 start(MAX_RANK)
         integer*8 edge(MAX_RANK)
         integer*8 index(MAX_RANK)
@@ -754,12 +828,12 @@ define([TEST_NFMPI_IGET_VARM],dnl
         integer*8 sstride(MAX_RANK)
         integer*8 stride(MAX_RANK)
         integer*8 imap(MAX_RANK)
-        logical canConvert     
+        logical canConvert
         DATATYPE($1, value, (MAX_NELS))
         doubleprecision expect(MAX_NELS)
         doubleprecision val
         integer ud_shift
-        integer err_w, reqid(1), st(1)      
+        integer err_w, reqid(1), st(1)
 
         nok = 0
 
@@ -767,7 +841,7 @@ define([TEST_NFMPI_IGET_VARM],dnl
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_open: ', err)
         do 1, i = 1, numVars
-            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
             if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assertion'
             if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assertion'
@@ -777,20 +851,18 @@ define([TEST_NFMPI_IGET_VARM],dnl
                 stride(j) = 1
                 imap(j) = 1
 2           continue
-            err = nfmpi_iget_varm_$1(BAD_ID, i, start, edge,
-     +                           stride, imap, value,reqid(1))
+            err = nfmpi_iget_varm_$1(BAD_ID, i,
+     +            start, edge, stride, imap, value,reqid(1))
             if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
-            err = nfmpi_iget_varm_$1(ncid, BAD_VARID, start,
-     +                           edge, stride, imap, value,reqid(1))
+            err = nfmpi_iget_varm_$1(ncid, BAD_VARID,
+     +            start, edge, stride, imap, value,reqid(1))
             if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
                 start(j) = var_shape(j,i) + 1
-                err = nfmpi_iget_varm_$1(ncid, i, start, edge,
-     +                                stride, imap, value,reqid(1))
-                if (err .EQ. NF_NOERR)
-     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                err = nfmpi_iget_varm_$1(ncid, i,
+     +                start, edge, stride, imap, value,reqid(1))
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -800,10 +872,8 @@ define([TEST_NFMPI_IGET_VARM],dnl
                 endif
                 start(j) = 1
                 edge(j) = var_shape(j,i) + 1
-                err = nfmpi_iget_varm_$1(ncid, i, start, edge,
-     +                                stride, imap, value,reqid(1))
-                if (err .EQ. NF_NOERR)
-     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                err = nfmpi_iget_varm_$1(ncid, i,
+     +                start, edge, stride, imap, value,reqid(1))
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -813,10 +883,8 @@ define([TEST_NFMPI_IGET_VARM],dnl
                 endif
                 edge(j) = 1
                 stride(j) = 0
-                err = nfmpi_iget_varm_$1(ncid, i, start, edge,
-     +                                stride, imap, value, reqid(1))
-                if (err .EQ. NF_NOERR)
-     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                err = nfmpi_iget_varm_$1(ncid, i,
+     +                start, edge, stride, imap, value, reqid(1))
                 if (.not. canConvert) then
                     if (err .ne. NF_ECHAR)
      +                  call errore('conversion: ', err)
@@ -826,19 +894,77 @@ define([TEST_NFMPI_IGET_VARM],dnl
                 endif
                 stride(j) = 1
 3           continue
-C           Choose a random point dividing each dim into 2 parts 
-C           get 2^rank (nslabs) slabs so defined 
+
+C           /* Check non-scalars for correct error returned even when */
+C           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 4, j = 1, var_rank(i)
+                    edge(j) = 0
+4               continue
+                err = nfmpi_iget_varm_$1(BAD_ID, i,
+     +                start, edge, stride, imap, value,reqid(1))
+                if (err .ne. NF_EBADID)
+     +              call errore('bad ncid: ', err)
+                err = nfmpi_iget_varm_$1(ncid, BAD_VARID,
+     +                start, edge, stride, imap, value,reqid(1))
+                if (err .ne. NF_ENOTVAR)
+     +              call errore('bad var id: ', err)
+                do 5, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_iget_varm_$1(ncid, i,
+     +                    start, edge, stride, imap, value,reqid(1))
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+#ifdef RELAX_COORD_BOUND
+                        if (err .ne. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+#else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+#endif
+                    endif
+                    start(j) = var_shape(j,i) + 2
+                    err = nfmpi_iget_varm_$1(ncid, i,
+     +                    start, edge, stride, imap, value,reqid(1))
+                    if (.NOT. canConvert) then
+                        if (err .NE. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+5               continue
+                err = nfmpi_iget_varm_$1(ncid, i,
+     +                start, edge, stride, imap, value,reqid(1))
+                if (canConvert) then
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                endif
+                do 6, j = 1, var_rank(i)
+                    edge(j) = 1
+6               continue
+            endif
+
+C           Choose a random point dividing each dim into 2 parts
+C           get 2^rank (nslabs) slabs so defined
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
-C           /* bits of k determine whether to get lower or upper part 
+7           continue
+C           /* bits of k determine whether to get lower or upper part
 C            * of dim
 C            * choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift((k-1), -(j-1)), 2) .ne. 0) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -853,19 +979,19 @@ C            * choose random stride from 1 to edge */
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * int(stride(j))
-6               continue
-                do 7, m = 1, nstarts
+9               continue
+                do 10, m = 1, nstarts
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
-                        count(j) = 1 + (edge(j) - index(j)) / 
+                    do 11, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) /
      +                                  stride(j)
                         nels = nels * int(count(j))
                         index(j) = index(j) + start(j) - 1
-8                   continue
-C                   Random choice of forward or backward 
+11                   continue
+C                   Random choice of forward or backward
 C    /* TODO
 C                   if ( roll(2) ) then
 C                       for (j = 0 j < var_rank(i) j++) {
@@ -876,83 +1002,80 @@ C                   end if
 C     */
                     if (var_rank(i) .gt. 0) then
                         imap(1) = 1
-                        do 9, j = 2, var_rank(i)
+                        do 12, j = 2, var_rank(i)
                             imap(j) = imap(j-1) * count(j-1)
-9                       continue
+12                      continue
                     end if
                     allInIntRange = .true.
                     allInExtRange = .true.
-                    do 10, j = 1, nels
-                        err = index2indexes(j, var_rank(i), count, 
+                    do 13, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count,
      +                                      index2)
                         if (err .ne. NF_NOERR)
      +                      call error('error in index2indexes 1')
-                        do 11, d = 1, var_rank(i)
-                            index2(d) = index(d) + (index2(d)-1) * 
+                        do 14, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) *
      +                                  stride(d)
-11                      continue
-                        expect(j) = hash4(var_type(i), var_rank(i), 
-     +                                    index2, NFT_ITYPE($1))
+14                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i),
+     +                                    index2)
                         if (inRange3(expect(j),var_type(i),
      +                               NFT_ITYPE($1))) then
-                            allInIntRange = 
+                            allInIntRange =
      +                          allInIntRange .and.
      +                          in_internal_range(NFT_ITYPE($1),
      +                                            expect(j))
                         else
                             allInExtRange = .false.
                         end if
-10                  continue
+13                  continue
                     err = nfmpi_iget_varm_$1(ncid,i,index,count,
      +                                   stride,imap, value, reqid(1))
                     if (err .EQ. NF_NOERR)
      +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                    if (canConvert) then
-                        if (allInExtRange) then
-                            if (allInIntRange) then
-                                if (st(1) .ne. 0)
-     +                              call error(nfmpi_strerror(st(1)))
-                            else
-                                if (st(1) .ne. NF_ERANGE)
-     +                              call errore('Range error: ', st(1))
-                            end if
+                    if (.NOT. canConvert) then
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                        goto 10
+                    end if
+                    if (allInExtRange) then
+                        if (allInIntRange) then
+                            if (st(1) .ne. 0)
+     +                          call error(nfmpi_strerror(st(1)))
                         else
-                            if (st(1) .ne. 0 .and. st(1) .ne. NF_ERANGE)
-     +                          call errore('OK or Range error: ',st(1))
+                            if (st(1) .ne. NF_ERANGE)
+     +                          call errore('Range error: ', st(1))
                         end if
-                        do 12, j = 1, nels
-                            if (inRange3(expect(j),var_type(i),
-     +                                   NFT_ITYPE($1)) .and.
-     +                          in_internal_range(NFT_ITYPE($1),
-     +                                            expect(j))) then
-                                val = ARITH3($1, value, j)
-                                if (.not.equal(val, expect(j),
-     +                                         var_type(i), 
-     +                                         NFT_ITYPE($1))) then
-                                    call error(
-     +                                  'value read not that expected')
-                                    if (verbose) then
-                                        call error(' ')
-                                        call errori('varid: ', i)
-                                        call errorc('var_name: ', 
-     +                                          var_name(i))
-                                        call errori('element number: ',
-     +                                              j)
-                                        call errord('expect: ', 
-     +                                              expect(j))
-                                        call errord('got: ', val)
-                                    end if
-                                else
-                                    nok = nok + 1
-                                end if
-                            end if
-12                      continue
                     else
-                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
-     +                      call errore('wrong type: ', err)
+                        if (st(1) .ne. 0 .and. st(1) .ne. NF_ERANGE)
+     +                      call errore('OK or Range error: ',st(1))
                     end if
-7               continue
-5           continue
+                    do 15, j = 1, nels
+                        if (inRange3(expect(j),var_type(i),
+     +                               NFT_ITYPE($1)) .and.
+     +                      in_internal_range(NFT_ITYPE($1),
+     +                                        expect(j))) then
+                            val = ARITH3($1, value, j)
+                            if (.not.equal(val, expect(j),var_type(i),
+     +                                     NFT_ITYPE($1))) then
+                                call error(
+     +                              'value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('var_name: ',
+     +                                      var_name(i))
+                                    call errori('element number: ',j)
+                                    call errord('expect: ',expect(j))
+                                    call errord('got: ', val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+15                  continue
+10              continue
+8           continue
 1       continue
         err = nfmpi_close(ncid)
         if (err .ne. NF_NOERR)
@@ -961,15 +1084,7 @@ C     */
         end
 ])dnl
 
-divert(0)dnl
-dnl If you see this line, you can ignore the next one.
-C Do not edit this file. It is produced from the corresponding .m4 source */
-
-C*********************************************************************
-C   Copyright 1996, UCAR/Unidata
-C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
-C   $Id: test_iget.m4 2224 2015-12-16 06:10:36Z wkliao $
-C*********************************************************************
+dnl divert(0)dnl
 
 TEST_NFMPI_IGET_VAR1(text)
 #ifdef NF_INT1_T
diff --git a/test/nf_test/test_iput.m4 b/test/nf_test/test_iput.m4
index 25670af..bf17724 100644
--- a/test/nf_test/test_iput.m4
+++ b/test/nf_test/test_iput.m4
@@ -1,4 +1,18 @@
-divert(-1)
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl This file is supposed to be the same as PnetCDF's test_iput.m4
+dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
+dnl
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_iput.m4 2618 2016-11-14 22:47:18Z wkliao $
+
+dnl divert(-1)
 
 dnl This is m4 source.
 dnl Process using m4 to produce FORTRAN language file.
@@ -84,31 +98,35 @@ define([MAKE_DOUBLE], [dnl
 ifelse($1, text, dble(ichar($2)), dble($2))[]dnl
 ])
 
-dnl  MAKE_TYPE(funf_suffix, var)
+dnl  MAKE_TYPE(itype, constant)
 dnl
 define([MAKE_TYPE], [dnl
-ifelse($1, text, char(int($2)),
-       ifelse($1, int, INT($2),
-       ifelse($1, real, REAL($2),
-       ifelse($1, double, DBLE($2),
-       $2))))[]dnl
+ifelse($1, text,   char(INT($2)),
+       $1, real,   REAL($2),
+       $1, double, DBLE($2),
+                   $2)[]dnl
 ])
 
-dnl  MAKE_TYPE2(funf_suffix, var_dest, var_src)
+dnl Use GNU intrinsic INT if available
+define([ConvInt1], [ifdef([HAVE_F77_INT1],INT1($1),ifdef([HAVE_F77_GNU_INT],INT($1,1),$1))])dnl
+define([ConvInt2], [ifdef([HAVE_F77_INT2],INT2($1),ifdef([HAVE_F77_GNU_INT],INT($1,2),$1))])dnl
+define([ConvInt8], [ifdef([HAVE_F77_INT8],INT8($1),ifdef([HAVE_F77_GNU_INT],INT($1,8),$1))])dnl
+
+dnl  MAKE_TYPE2(itype, dest, src)
 dnl
-define([MAKE_TYPE2], [dnl
-ifelse($1, text, $2 = char(int($3)),
-       ifelse($1, int, $2 = INT($3),
-       ifelse($1, int8,
-                  if ($3 .EQ. X_INT8_MAX) then
-                      $2 = X_INT8_MAX
-                  else
-                      $2 = $3
-                  endif,
-       ifelse($1, real, $2 = REAL($3),
-       ifelse($1, double, $2 = DBLE($3),
-       $2 = $3)))))[]dnl
-])
+define([MAKE_TYPE2], [ifelse($1, text,   $2 = char(INT($3)),
+                             $1, real,   $2 = REAL($3),
+                             $1, double, $2 = DBLE($3),
+                             $1, int,    $2 = INT($3),
+                             $1, int1,   $2 = ConvInt1($3),
+                             $1, int2,   $2 = ConvInt2($3),
+                             $1, int8,
+                      if ($3 .EQ. X_INT8_MAX) then
+                          $2 = X_INT8_MAX
+                      else
+                          $2 = ConvInt8($3)
+                      endif,
+                             $2 = $3)])
 
 dnl TEST_NFMPI_IPUT_VAR1(TYPE)
 dnl
@@ -153,45 +171,42 @@ define([TEST_NFMPI_IPUT_VAR1],dnl
 2           continue
             err = nfmpi_iput_var1_$1(BAD_ID, i, index, value,
      +                               reqid(1))
-            if (err .ne. NF_EBADID) 
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
             err = nfmpi_iput_var1_$1(ncid, BAD_VARID,
      +                           index, value,reqid(1))
-            if (err .ne. NF_ENOTVAR) 
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .gt. 1) then         !/* skip record dim */
-                    index(j) = var_shape(j,i) + 1
-                    err = nfmpi_iput_var1_$1(ncid, i,
-     +                                   index, value,reqid(1))
-                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EINVALCOORDS)
-     +                      call errore('bad index: ', err)
-                    endif
-                    index(j) = 0
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                index(j) = var_shape(j,i) + 1
+                err = nfmpi_iput_var1_$1(ncid, i,
+     +                index, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad index: ', err)
+                endif
+                index(j) = 0
 3           continue
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+                err = index2indexes(j, var_rank(i), var_shape(1,i),
      +                              index)
-                if (err .ne. NF_NOERR) 
+                if (err .ne. NF_NOERR)
      +              call error('error in index2indexes 1')
                 val = hash_$1(var_type(i),var_rank(i),
      +                            index, NFT_ITYPE($1))
                 MAKE_TYPE2($1, value, val)
-                err = nfmpi_iput_var1_$1(ncid, i, index, value,
-     +                                   reqid(1))
+                err = nfmpi_iput_var1_$1(ncid, i,
+     +                index, value, reqid(1))
                 if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
      +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
                 if (canConvert) then
                     val = ARITH_VAR1($1, value)
                     if (inRange3(val, var_type(i), NFT_ITYPE($1))) then
-                        if (st(1) .ne. 0)
+                        if (st(1) .ne. NF_NOERR)
      +                      call error(nfmpi_strerror(st(1)))
                     else
                         if (err .ne. NF_ERANGE)
@@ -205,14 +220,14 @@ define([TEST_NFMPI_IPUT_VAR1],dnl
 4           continue
 1       continue
         err = nfmpi_close(ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
 
         call check_vars_$1(scratch)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed: ', 
+     +      call errorc('delete of scratch file failed: ',
      +                  scratch)
         end
 ])dnl
@@ -258,11 +273,11 @@ define([TEST_NFMPI_IPUT_VAR],dnl
             canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
             err = nfmpi_iput_var_$1(BAD_ID, i, value,reqid(1))
-            if (err .ne. NF_EBADID) 
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
             err = nfmpi_iput_var_$1(ncid, BAD_VARID, value,
      +                                   reqid(1))
-            if (err .ne. NF_ENOTVAR) 
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             nels = 1
             do 3, j = 1, var_rank(i)
@@ -270,9 +285,9 @@ define([TEST_NFMPI_IPUT_VAR],dnl
 3           continue
             allInExtRange = .true.
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+                err = index2indexes(j, var_rank(i), var_shape(1,i),
      +                              index)
-                if (err .ne. NF_NOERR) 
+                if (err .ne. NF_NOERR)
      +              call error('error in index2indexes 1')
                 val = hash_$1(var_type(i), var_rank(i),
      +                        index, NFT_ITYPE($1))
@@ -335,9 +350,9 @@ C           Only test record variables here
 6               continue
                 allInExtRange = .true.
                 do 7, j = 1, nels
-                    err = index2indexes(j, var_rank(i), var_shape(1,i), 
+                    err = index2indexes(j, var_rank(i), var_shape(1,i),
      +                              index)
-                    if (err .ne. NF_NOERR) 
+                    if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes()')
                     val = hash_$1(var_type(i), var_rank(i),
      +                            index, NFT_ITYPE($1))
@@ -365,14 +380,14 @@ C           Only test record variables here
             endif
 5       continue
         err = nfmpi_close(ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
 
         call check_vars_$1(scratch)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed: ', 
+     +      call errorc('delete of scratch file failed: ',
      +                  scratch)
         end
 ])dnl
@@ -432,105 +447,111 @@ define([TEST_NFMPI_IPUT_VARA],dnl
                 start(j) = 1
                 edge(j) = 1
 2           continue
-            err = nfmpi_iput_vara_$1(BAD_ID, i, start,
-     +                  edge, value,reqid(1))
-            if (err .ne. NF_EBADID) 
+            err = nfmpi_iput_vara_$1(BAD_ID, i,
+     +            start, edge, value,reqid(1))
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
             err = nfmpi_iput_vara_$1(ncid, BAD_VARID,
-     +                  start, edge, value,reqid(1))
-            if (err .ne. NF_ENOTVAR) 
+     +            start, edge, value,reqid(1))
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
-                    start(j) = var_shape(j,i) + 1
-                    err = nfmpi_iput_vara_$1(ncid, i, start, 
-     +                                   edge, value,reqid(1))
-                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +                  err_w = nfmpi_wait_all(ncid, 1, reqid, st)
-                        ! NF_ERANGE is not a fatal error
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EINVALCOORDS)
-     +                      call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nfmpi_iput_vara_$1(ncid, i, start, 
-     +                                   edge, value,reqid(1))
-                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +                  err_w = nfmpi_wait_all(ncid, 1, reqid, st)
-                        ! NF_ERANGE is not a fatal error
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EEDGE)
-     +                      call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_iput_vara_$1(ncid, i,
+     +                start, edge, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_iput_vara_$1(ncid, i,
+     +                start, edge, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
 3           continue
 
 C           /* Check correct error returned even when nothing to put */
-            do 20, j = 1, var_rank(i)
+            do 4, j = 1, var_rank(i)
                   edge(j) = 0
-20          continue
-            err = nfmpi_iput_vara_$1(BAD_ID, i, start,
-     +              edge, value,reqid(1))
-            if (err .ne. NF_EBADID) 
+4           continue
+            err = nfmpi_iput_vara_$1(BAD_ID, i,
+     +            start, edge, value,reqid(1))
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
             err = nfmpi_iput_vara_$1(ncid, BAD_VARID,
-     +              start, edge, value,reqid(1))
-            if (err .ne. NF_ENOTVAR) 
+     +            start, edge, value,reqid(1))
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
-            do 21, j = 1, var_rank(i)
-                if (var_dimid(j,i) .gt. 1) then     ! skip record dim
-                    start(j) = var_shape(j,i) + 1
-                    err = nfmpi_iput_vara_$1(ncid, i, start,
-     +                      edge, value,reqid(1))
-                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +                  err_w = nfmpi_wait_all(ncid, 1, reqid, st)
-                        ! NF_ERANGE is not a fatal error
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EINVALCOORDS)
-     +                      call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_iput_vara_$1(ncid, i,
+     +                start, edge, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
+#else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+#endif
                 endif
-21          continue
-            err = nfmpi_iput_vara_$1(ncid, i, start, edge, value,
-     +                                   reqid(1))
-            if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +          err_w = nfmpi_wait_all(ncid, 1, reqid, st)
-                ! NF_ERANGE is not a fatal error
+                start(j) = var_shape(j,i) + 2
+                err = nfmpi_iput_vara_$1(ncid, i,
+     +                start, edge, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nfmpi_iput_vara_$1(ncid, i,
+     +            start, edge, value, reqid(1))
             if (canConvert) then
-                if (st(1) .ne. 0) 
+                if (err .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(err))
+                err = nfmpi_wait_all(ncid,1,reqid,st)
+                if (err .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(err))
+                if (st(1) .ne. NF_NOERR)
      +              call error(nfmpi_strerror(st(1)))
             else
                 if (err .ne. NF_ECHAR)
      +              call errore('wrong type: ', err)
             endif
-            do 22, j = 1, var_rank(i)
+            do 6, j = 1, var_rank(i)
                   edge(j) = 1
-22          continue
-
+6           continue
 
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
-                !/* bits of k determine whether to put lower or upper part of dim */
-            do 5, k = 1, nslabs
+7           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            do 8, k = 1, nslabs
                 nels = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -539,22 +560,22 @@ C           /* Check correct error returned even when nothing to put */
                         edge(j) = var_shape(j,i) - mid(j)
                     end if
                     nels = nels * int(edge(j))
-6               continue
+9               continue
                 allInExtRange = .true.
-                do 7, j = 1, nels
+                do 10, j = 1, nels
                     err = index2indexes(j, var_rank(i), edge, index)
-                    if (err .ne. NF_NOERR) 
+                    if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes 1')
-                    do 8, d = 1, var_rank(i)
+                    do 11, d = 1, var_rank(i)
                         index(d) = index(d) + start(d) - 1
-8                   continue
+11                  continue
                     val = hash_$1(var_type(i), var_rank(i),
      +                            index, NFT_ITYPE($1))
                     MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
                     val = ARITH3($1, value, j)
                     allInExtRange = allInExtRange .and.
      +                  inRange3(val, var_type(i), NFT_ITYPE($1))
-7               continue
+10              continue
                 err = nfmpi_iput_vara_$1(ncid, i, start,
      +                  edge, value,reqid(1))
                 if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
@@ -562,7 +583,7 @@ C           /* Check correct error returned even when nothing to put */
                     ! NF_ERANGE is not a fatal error?
                 if (canConvert) then
                     if (allInExtRange) then
-                        if (st(1) .ne. 0) 
+                        if (st(1) .ne. NF_NOERR)
      +                      call error(nfmpi_strerror(st(1)))
                     else
                         if (err .ne. NF_ERANGE)
@@ -572,18 +593,18 @@ C           /* Check correct error returned even when nothing to put */
                     if (nels .gt. 0 .and. err .ne. NF_ECHAR)
      +                  call errore('wrong type: ', err)
                 end if
-5           continue
+8           continue
 1       continue
 
         err = nfmpi_close(ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
 
         call check_vars_$1(scratch)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed: ', 
+     +      call errorc('delete of scratch file failed: ',
      +          scratch)
         end
 ])dnl
@@ -650,76 +671,123 @@ define([TEST_NFMPI_IPUT_VARS],dnl
                 edge(j) = 1
                 stride(j) = 1
 2           continue
-            err = nfmpi_iput_vars_$1(BAD_ID, i, start,
-     +                  edge, stride, value,reqid(1))
-            if (err .ne. NF_EBADID) 
+            err = nfmpi_iput_vars_$1(BAD_ID, i,
+     +            start, edge, stride, value,reqid(1))
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
-            err = nfmpi_iput_vars_$1(ncid, BAD_VARID, start,
-     +                           edge, stride, 
-     +                           value,reqid(1))
-            if (err .ne. NF_ENOTVAR) 
+            err = nfmpi_iput_vars_$1(ncid, BAD_VARID,
+     +            start, edge, stride, value,reqid(1))
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    ! skip record dim
-                    start(j) = var_shape(j,i) + 1
-                    err = nfmpi_iput_vars_$1(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   value,reqid(1))
-                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                        ! NF_ERANGE is not a fatal error?
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EINVALCOORDS)
-     +                          call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nfmpi_iput_vars_$1(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   value,reqid(1))
-                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                        ! NF_ERANGE is not a fatal error?
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EEDGE)
-     +                      call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                    stride(j) = 0
-                    err = nfmpi_iput_vars_$1(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   value,reqid(1))
-                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                        ! NF_ERANGE is not a fatal error?
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_ESTRIDE)
-     +                      call errore('bad stride: ', err)
-                    endif
-                    stride(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_iput_vars_$1(ncid, i,
+     +                start, edge, stride, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_iput_vars_$1(ncid, i,
+     +                start, edge, stride, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nfmpi_iput_vars_$1(ncid, i,
+     +                start, edge, stride, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_ESTRIDE)
+     +                  call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
 3           continue
+
+C           /* Check correct error returned even when nothing to put */
+            do 4, j = 1, var_rank(i)
+                  edge(j) = 0
+4           continue
+            err = nfmpi_iput_vars_$1(BAD_ID, i,
+     +            start, edge, stride, value,reqid(1))
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iput_vars_$1(ncid, BAD_VARID,
+     +            start, edge, stride, value,reqid(1))
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_iput_vars_$1(ncid, i,
+     +                start, edge, stride, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
+#else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+#endif
+                endif
+                start(j) = var_shape(j,i) + 2
+                err = nfmpi_iput_vars_$1(ncid, i,
+     +                start, edge, stride, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nfmpi_iput_vars_$1(ncid, i,
+     +            start, edge, stride, value, reqid(1))
+            if (canConvert) then
+                if (err .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(err))
+                err = nfmpi_wait_all(ncid,1,reqid,st)
+                if (err .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(err))
+                if (st(1) .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(st(1)))
+            else
+                if (err .ne. NF_ECHAR)
+     +              call errore('wrong type: ', err)
+            endif
+            do 6, j = 1, var_rank(i)
+                  edge(j) = 1
+6           continue
+
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
             !/* bits of k determine whether to put lower or upper part of dim */
             !/* choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -734,17 +802,17 @@ define([TEST_NFMPI_IPUT_VARS],dnl
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * int(stride(j))
-6               continue
-                do 7, m = 1, nstarts
+9               continue
+                do 10, m = 1, nstarts
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) / stride(j)
                         nels = nels * int(count(j))
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                   continue
                     !/* Random choice of forward or backward */
 C/* TODO
 C                   if ( roll(2) ) {
@@ -755,31 +823,30 @@ C                       }
 C                   }
 C*/
                     allInExtRange = .true.
-                    do 9, j = 1, nels
-                        err = index2indexes(j, var_rank(i), count, 
+                    do 12, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count,
      +                                      index2)
                         if (err .ne. NF_NOERR)
      +                      call error('error in index2indexes')
-                        do 10, d = 1, var_rank(i)
-                            index2(d) = index(d) + 
+                        do 13, d = 1, var_rank(i)
+                            index2(d) = index(d) +
      +                                  (index2(d)-1) * stride(d)
-10                      continue
+13                      continue
                         val = hash_$1(var_type(i), var_rank(i),
      +                                index2, NFT_ITYPE($1))
                         MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
                         val = ARITH3($1, value, j)
                         allInExtRange = allInExtRange .and.
-     +                      inRange3(val, var_type(i), 
+     +                      inRange3(val, var_type(i),
      +                               NFT_ITYPE($1))
-9                   continue
-                    err = nfmpi_iput_vars_$1(ncid, i, index,
-     +                                   count, stride,
-     +                                   value,reqid(1))
+12                   continue
+                    err = nfmpi_iput_vars_$1(ncid, i,
+     +                    index, count, stride, value,reqid(1))
                     if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
      +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
                     if (canConvert) then
                         if (allInExtRange) then
-                            if (st(1) .ne. 0) 
+                            if (st(1) .ne. NF_NOERR)
      +                          call error(nfmpi_strerror(st(1)))
                         else
                             if (err .ne. NF_ERANGE)
@@ -789,19 +856,19 @@ C*/
                         if (nels .gt. 0 .and. err .ne. NF_ECHAR)
      +                      call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10               continue
+8           continue
 1       continue
 
         err = nfmpi_close(ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
 
         call check_vars_$1(scratch)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed:', 
+     +      call errorc('delete of scratch file failed:',
      +          scratch)
         end
 ])dnl
@@ -872,77 +939,123 @@ define([TEST_NFMPI_IPUT_VARM],dnl
                 stride(j) = 1
                 imap(j) = 1
 2           continue
-            err = nfmpi_iput_varm_$1(BAD_ID, i, start,
-     +                           edge, stride, imap, 
-     +                           value,reqid(1))
-            if (err .ne. NF_EBADID) 
+            err = nfmpi_iput_varm_$1(BAD_ID, i,
+     +            start, edge, stride, imap, value,reqid(1))
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
-            err = nfmpi_iput_varm_$1(ncid, BAD_VARID, start,
-     +                           edge, stride, 
-     +                           imap, value,reqid(1))
-            if (err .ne. NF_ENOTVAR) 
+            err = nfmpi_iput_varm_$1(ncid, BAD_VARID,
+     +            start, edge, stride, imap, value,reqid(1))
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
-                    start(j) = var_shape(j,i) + 1
-                    err = nfmpi_iput_varm_$1(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   imap, value,reqid(1))
-                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                        ! NF_ERANGE is not a fatal error?
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EINVALCOORDS)
-     +                      call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nfmpi_iput_varm_$1(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   imap, value,reqid(1))
-                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                        ! NF_ERANGE is not a fatal error?
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EEDGE)
-     +                      call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                    stride(j) = 0
-                    err = nfmpi_iput_varm_$1(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   imap, value,reqid(1))
-                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
-     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
-                        ! NF_ERANGE is not a fatal error?
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_ESTRIDE)
-     +                      call errore('bad stride: ', err)
-                    endif
-                    stride(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_iput_varm_$1(ncid, i,
+     +                start, edge, stride, imap, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_iput_varm_$1(ncid, i,
+     +                start, edge, stride, imap, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nfmpi_iput_varm_$1(ncid, i,
+     +                start, edge, stride, imap, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_ESTRIDE)
+     +                  call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
 3           continue
+
+C           /* Check correct error returned even when nothing to put */
+            do 4, j = 1, var_rank(i)
+                  edge(j) = 0
+4           continue
+            err = nfmpi_iput_varm_$1(BAD_ID, i,
+     +            start, edge, stride, imap, value,reqid(1))
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iput_varm_$1(ncid, BAD_VARID,
+     +            start, edge, stride, imap, value,reqid(1))
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_iput_varm_$1(ncid, i,
+     +                start, edge, stride, imap, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
+#else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+#endif
+                endif
+                start(j) = var_shape(j,i) + 2
+                err = nfmpi_iput_varm_$1(ncid, i,
+     +                start, edge, stride, imap, value,reqid(1))
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nfmpi_iput_varm_$1(ncid, i,
+     +            start, edge, stride, imap, value, reqid(1))
+            if (canConvert) then
+                if (err .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(err))
+                err = nfmpi_wait_all(ncid,1,reqid,st)
+                if (err .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(err))
+                if (st(1) .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(st(1)))
+            else
+                if (err .ne. NF_ECHAR)
+     +              call errore('wrong type: ', err)
+            endif
+            do 6, j = 1, var_rank(i)
+                  edge(j) = 1
+6           continue
+
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
             !/* bits of k determine whether to put lower or upper part of dim */
             !/* choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -957,59 +1070,58 @@ define([TEST_NFMPI_IPUT_VARM],dnl
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * int(stride(j))
-6               continue
-                do 7, m = 1, nstarts
+9               continue
+                do 10, m = 1, nstarts
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) / stride(j)
                         nels = nels * int(count(j))
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
                     !/* Random choice of forward or backward */
 C/* TODO
 C                   if ( roll(2) ) then
-C                       do 9, j = 1, var_rank(i)
-C                           index(j) = index(j) + 
+C                       do 12, j = 1, var_rank(i)
+C                           index(j) = index(j) +
 C     +                         (count(j) - 1) * stride(j)
 C                           stride(j) = -stride(j)
-C9                      continue
+C12                     continue
 C                   end if
 C*/
                     if (var_rank(i) .gt. 0) then
                         imap(1) = 1
-                        do 10, j = 2, var_rank(i)
+                        do 13, j = 2, var_rank(i)
                             imap(j) = imap(j-1) * count(j-1)
-10                      continue
+13                      continue
                     end if
                     allInExtRange = .true.
-                    do 11 j = 1, nels
-                        err = index2indexes(j, var_rank(i), count, 
+                    do 14 j = 1, nels
+                        err = index2indexes(j, var_rank(i), count,
      +                                      index2)
                         if (err .ne. NF_NOERR)
      +                      call error('error in index2indexes')
-                        do 12, d = 1, var_rank(i)
-                            index2(d) = index(d) + 
+                        do 15, d = 1, var_rank(i)
+                            index2(d) = index(d) +
      +                          (index2(d)-1) * stride(d)
-12                      continue
-                        val = hash_$1(var_type(i),var_rank(i), 
+15                      continue
+                        val = hash_$1(var_type(i),var_rank(i),
      +                                index2, NFT_ITYPE($1))
                         MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
                         val = ARITH3($1, value, j)
                         allInExtRange = allInExtRange .and.
-     +                      inRange3(val, var_type(i), 
+     +                      inRange3(val, var_type(i),
      +                               NFT_ITYPE($1))
-11                  continue
-                    err = nfmpi_iput_varm_$1(ncid,i,index,count,
-     +                                   stride,imap,
-     +                                   value,reqid(1))
+14                  continue
+                    err = nfmpi_iput_varm_$1(ncid,i,
+     +                   index,count, stride,imap, value,reqid(1))
                     if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
      +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
                     if (canConvert) then
                         if (allInExtRange) then
-                            if (st(1) .ne. 0)
+                            if (st(1) .ne. NF_NOERR)
      +                          call error(nfmpi_strerror(st(1)))
                         else
                             if (err .ne. NF_ERANGE)
@@ -1019,33 +1131,25 @@ C*/
                         if (nels .gt. 0 .and. err .ne. NF_ECHAR)
      +                      call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 1       continue
 
         err = nfmpi_close(ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
 
         call check_vars_$1(scratch)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed:', 
+     +      call errorc('delete of scratch file failed:',
      +          scratch)
         end
 ])dnl
 
 
-divert(0)dnl
-dnl If you see this line, you can ignore the next one.
-C Do not edit this file. It is produced from the corresponding .m4 source */
-
-C********************************************************************
-C   Copyright 1996, UCAR/Unidata
-C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
-C   $Id: test_iput.m4 2232 2015-12-16 22:16:52Z wkliao $
-C********************************************************************
+dnl divert(0)dnl
 
 TEST_NFMPI_IPUT_VAR1(text)
 #ifdef NF_INT1_T
diff --git a/test/nf_test/test_put.m4 b/test/nf_test/test_put.m4
index 841cd1b..13b4307 100644
--- a/test/nf_test/test_put.m4
+++ b/test/nf_test/test_put.m4
@@ -1,4 +1,18 @@
-divert(-1)
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl This file is supposed to be the same as PnetCDF's test_put.m4
+dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
+dnl
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_put.m4 2618 2016-11-14 22:47:18Z wkliao $
+
+dnl divert(-1)
 
 dnl This is m4 source.
 dnl Process using m4 to produce FORTRAN language file.
@@ -84,31 +98,35 @@ define([MAKE_DOUBLE], [dnl
 ifelse($1, text, dble(ichar($2)), dble($2))[]dnl
 ])
 
-dnl  MAKE_TYPE(funf_suffix, var)
+dnl  MAKE_TYPE(itype, constant)
 dnl
 define([MAKE_TYPE], [dnl
-ifelse($1, text, char(int($2)),
-       ifelse($1, int, INT($2),
-       ifelse($1, real, REAL($2),
-       ifelse($1, double, DBLE($2),
-       $2))))[]dnl
+ifelse($1, text,   char(INT($2)),
+       $1, real,   REAL($2),
+       $1, double, DBLE($2),
+                   $2)[]dnl
 ])
 
-dnl  MAKE_TYPE2(funf_suffix, var_dest, var_src)
+dnl Use GNU intrinsic INT if available
+define([ConvInt1], [ifdef([HAVE_F77_INT1],INT1($1),ifdef([HAVE_F77_GNU_INT],INT($1,1),$1))])dnl
+define([ConvInt2], [ifdef([HAVE_F77_INT2],INT2($1),ifdef([HAVE_F77_GNU_INT],INT($1,2),$1))])dnl
+define([ConvInt8], [ifdef([HAVE_F77_INT8],INT8($1),ifdef([HAVE_F77_GNU_INT],INT($1,8),$1))])dnl
+
+dnl  MAKE_TYPE2(itype, dest, src)
 dnl
-define([MAKE_TYPE2], [dnl
-ifelse($1, text, $2 = char(int($3)),
-       ifelse($1, int, $2 = INT($3),
-       ifelse($1, int8, 
-                  if ($3 .EQ. X_INT8_MAX) then 
-                      $2 = X_INT8_MAX 
-                  else 
-                      $2 = $3
-                  endif, 
-       ifelse($1, real, $2 = REAL($3),
-       ifelse($1, double, $2 = DBLE($3),
-       $2 = $3)))))[]dnl
-])
+define([MAKE_TYPE2], [ifelse($1, text,   $2 = char(INT($3)),
+                             $1, real,   $2 = REAL($3),
+                             $1, double, $2 = DBLE($3),
+                             $1, int,    $2 = INT($3),
+                             $1, int1,   $2 = ConvInt1($3),
+                             $1, int2,   $2 = ConvInt2($3),
+                             $1, int8,
+                      if ($3 .EQ. X_INT8_MAX) then
+                          $2 = X_INT8_MAX
+                      else
+                          $2 = ConvInt8($3)
+                      endif,
+                             $2 = $3)])
 
 dnl HASH(TYPE)
 dnl
@@ -133,7 +151,7 @@ C
         maximum = internal_max(itype)
 
         hash_$1 = max(minimum, min(maximum, hash4( type, rank,
-     +      index, itype)))
+     +      index)))
         end
 ])dnl
 
@@ -178,76 +196,65 @@ C
         err = nfmpi_open(comm, filename, NF_NOWRITE, info, ncid)
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_open: ', err)
-        err = nfmpi_begin_indep_data(ncid)
         do 1, i = 1, numVars
             canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
-            if (canConvert)  then
-                err = nfmpi_inq_var(ncid, i, name, datatype, ndims,
-     +                              dimids, ngatts)
+            if (.NOT. canConvert) go to 1
+            err = nfmpi_inq_var(ncid, i, name, datatype, ndims,
+     +                          dimids, ngatts)
+            if (err .ne. NF_NOERR)
+     +          call errore('nfmpi_inq_var: ', err)
+            if (name .ne. var_name(i))
+     +          call error('Unexpected var_name')
+            if (datatype .ne. var_type(i))
+     +          call error('Unexpected type')
+            if (ndims .ne. var_rank(i))
+     +          call error('Unexpected rank')
+            do 2, j = 1, ndims
+                err = nfmpi_inq_dim(ncid, dimids(j), name, length)
                 if (err .ne. NF_NOERR)
-     +              call errore('nfmpi_inq_var: ', err)
-                if (name .ne. var_name(i))
-     +              call error('Unexpected var_name')
-                if (datatype .ne. var_type(i))
-     +              call error('Unexpected type')
-                if (ndims .ne. var_rank(i))
-     +              call error('Unexpected rank')
-                do 2, j = 1, ndims
-                    err = nfmpi_inq_dim(ncid, dimids(j), name, 
-     +                   length)
-                    if (err .ne. NF_NOERR)
-     +                  call errore('nfmpi_inq_dim: ', err)
-                    if (length .ne. var_shape(j,i))
-     +                  call error('Unexpected shape')
-2               continue
-                do 3, j = 1, var_nels(i)
-                    err = index2indexes(j, var_rank(i), var_shape(1,i), 
-     +                                  index)
-                    if (err .ne. NF_NOERR)
-     +                  call error('error in index2indexes()')
-                    expect = hash4( var_type(i), var_rank(i), index, 
-     +                             NFT_ITYPE($1))
-                    err = nfmpi_get_var1_$1(ncid, i, index, 
-     +                      value)
-                    if (inRange3(expect,datatype,NFT_ITYPE($1)))  then
-                        if (in_internal_range(NFT_ITYPE($1), 
-     +                                        expect)) then
-                            if (err .ne. NF_NOERR)  then
-                                call errore
-     +                         ('nfmpi_get_var1_$1: ',
-     +                          err)
-                            else
-                                val = MAKE_ARITH_VAR1($1,value)
-                                if (.not.equal(
-     +                              val,
-     +                              expect,var_type(i),
-     +                              NFT_ITYPE($1)))  then
-                                    call error(
-     +                          'Var value read not that expected')
-                                    if (verbose)  then
-                                        call error(' ')
-                                        call errori('varid: %d', i)
-                                        call errorc('var_name: ', 
-     +                                          var_name(i))
-                                        call error('index:')
-                                        do 4, d = 1, var_rank(i)
-                                            intindex = int(index(d))
-                                            call errori(' ', intindex)
-4                                       continue
-                                        call errord('expect: ', expect)
-                                        call errord('got: ',  val)
-                                    end if
-                                else
-                                    nok = nok + 1
-                                end if
+     +              call errore('nfmpi_inq_dim: ', err)
+                if (length .ne. var_shape(j,i))
+     +              call error('Unexpected shape')
+2           continue
+            do 3, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),
+     +                              index)
+                if (err .ne. NF_NOERR)
+     +              call error('error in index2indexes()')
+                expect = hash4(var_type(i), var_rank(i), index)
+                err = nfmpi_get_var1_$1_all(ncid, i, index, value)
+                if (.NOT. inRange3(expect,datatype,NFT_ITYPE($1)))
+     +              go to 3
+                if (in_internal_range(NFT_ITYPE($1), expect)) then
+                    if (err .ne. NF_NOERR) then
+                        call errore (
+     +                  'nfmpi_get_var1_$1_all: ', err)
+                    else
+                        val = MAKE_ARITH_VAR1($1,value)
+                        if (.not.equal(val, expect,var_type(i),
+     +                      NFT_ITYPE($1)))  then
+                            call error(
+     +                      'Var value read not that expected')
+                            if (verbose)  then
+                                call error(' ')
+                                call errori('varid: %d', i)
+                                call errorc('var_name: ', var_name(i))
+                                call error('index:')
+                                do 4, d = 1, var_rank(i)
+                                    intindex = int(index(d))
+                                    call errori(' ', intindex)
+4                               continue
+                                call errord('expect: ', expect)
+                                call errord('got: ',  val)
                             end if
+                        else
+                            nok = nok + 1
                         end if
                     end if
-3               continue
-            end if
+                end if
+3           continue
 1       continue
-        err = nfmpi_end_indep_data(ncid)
         err = nfmpi_close (ncid)
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
@@ -260,7 +267,7 @@ dnl CHECK_ATTS(TYPE)         numeric only
 dnl
 define([CHECK_ATTS],dnl
 [dnl
-C/* 
+C/*
 C *  check all attributes in file which are (text/numeric) compatible with TYPE
 C *  ignore any attributes containing values outside range of TYPE
 C */
@@ -296,7 +303,7 @@ C */
                 canConvert = (ATT_TYPE(j,i) .eq. NF_CHAR) .eqv.
      +                       (NFT_ITYPE($1) .eq. NFT_TEXT)
                 if (canConvert) then
-                    err = nfmpi_inq_att(ncid, i, ATT_NAME(j,i), 
+                    err = nfmpi_inq_att(ncid, i, ATT_NAME(j,i),
      +                               datatype, length)
                     if (err .ne. NF_NOERR)
      +                  call errore('nfmpi_inq_att: ', err)
@@ -310,9 +317,8 @@ C */
                     nInExtRange = 0
                     do 4, k = 1, int(length)
                         ndx(1) = k
-                        expect(k) = hash4( datatype, -1, ndx, 
-     +                                    NFT_ITYPE($1))
-                        if (inRange3(expect(k), datatype, 
+                        expect(k) = hash4(datatype, -1, ndx)
+                        if (inRange3(expect(k), datatype,
      +                               NFT_ITYPE($1))) then
                             nInExtRange = nInExtRange + 1
                             if (in_internal_range(NFT_ITYPE($1),
@@ -320,9 +326,9 @@ C */
      +                          nInIntRange = nInIntRange + 1
                         end if
 4                   continue
-                    err = nfmpi_get_att_$1(ncid, i, 
+                    err = nfmpi_get_att_$1(ncid, i,
      +                                  ATT_NAME(j,i), value)
-                    if (nInExtRange .eq. length .and. 
+                    if (nInExtRange .eq. length .and.
      +                  nInIntRange .eq. length) then
                         if (err .ne. NF_NOERR)
      +                      call error(nfmpi_strerror(err))
@@ -332,8 +338,8 @@ C */
                     end if
                     do 3, k = 1, int(length)
                         if (inRange3(expect(k),datatype,NFT_ITYPE($1))
-     +                          .and. 
-     +                          in_internal_range(NFT_ITYPE($1), 
+     +                          .and.
+     +                          in_internal_range(NFT_ITYPE($1),
      +                                            expect(k))) then
                             val = MAKE_ARITH3($1,value,k)
                             if (.not.equal(
@@ -345,7 +351,7 @@ C */
                                 if (verbose) then
                                     call error(' ')
                                     call errori('varid: ', i)
-                                    call errorc('att_name: ', 
+                                    call errorc('att_name: ',
      +                                  ATT_NAME(j,i))
                                     call errori('element number: ', k)
                                     call errord('expect: ', expect(k))
@@ -356,7 +362,7 @@ C */
                             end if
                         end if
 3                   continue
-                end if                                               
+                end if
 2           continue
 1       continue
 
@@ -399,44 +405,42 @@ define([TEST_NFMPI_PUT_VAR1],dnl
         err = nfmpi_enddef(ncid)
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_enddef: ', err)
-        err = nfmpi_begin_indep_data(ncid)
         do 1, i = 1, numVars
             canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
             do 2, j = 1, var_rank(i)
                 index(j) = 1
 2           continue
-            err = nfmpi_put_var1_$1(BAD_ID, i, index, value)
-            if (err .ne. NF_EBADID) 
+            err = nfmpi_put_var1_$1_all(BAD_ID, i, index, value)
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
-            err = nfmpi_put_var1_$1(ncid, BAD_VARID,
+            err = nfmpi_put_var1_$1_all(ncid, BAD_VARID,
      +                           index, value)
-            if (err .ne. NF_ENOTVAR) 
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .gt. 1) then         !/* skip record dim */
-                    index(j) = var_shape(j,i) + 1
-                    err = nfmpi_put_var1_$1(ncid, i,
-     +                                   index, value)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EINVALCOORDS)
-     +                      call errore('bad index: ', err)
-                    endif
-                    index(j) = 0
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                index(j) = var_shape(j,i) + 1
+                err = nfmpi_put_var1_$1_all(ncid, i,
+     +                                      index, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad index: ', err)
+                endif
+                index(j) = 0
 3           continue
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+                err = index2indexes(j, var_rank(i), var_shape(1,i),
      +                              index)
-                if (err .ne. NF_NOERR) 
+                if (err .ne. NF_NOERR)
      +              call error('error in index2indexes 1')
                 val = hash_$1(var_type(i),var_rank(i),
      +                            index, NFT_ITYPE($1))
                 MAKE_TYPE2($1, value, val)
-                err = nfmpi_put_var1_$1(ncid, i, index, value)
+                err = nfmpi_put_var1_$1_all(ncid, i, index, value)
                 if (canConvert) then
                     val = ARITH_VAR1($1, value)
                     if (inRange3(val, var_type(i), NFT_ITYPE($1))) then
@@ -452,16 +456,15 @@ define([TEST_NFMPI_PUT_VAR1],dnl
                 end if
 4           continue
 1       continue
-        err = nfmpi_end_indep_data(ncid)
         err = nfmpi_close(ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
 
         call check_vars_$1(scratch)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed: ', 
+     +      call errorc('delete of scratch file failed: ',
      +                  scratch)
         end
 ])dnl
@@ -502,15 +505,14 @@ define([TEST_NFMPI_PUT_VAR],dnl
         err = nfmpi_enddef(ncid)
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_enddef: ', err)
-        err = nfmpi_begin_indep_data(ncid)
         do 1, i = 1, numVars
             canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
      +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
-            err = nfmpi_put_var_$1(BAD_ID, i, value)
-            if (err .ne. NF_EBADID) 
+            err = nfmpi_put_var_$1_all(BAD_ID, i, value)
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
-            err = nfmpi_put_var_$1(ncid, BAD_VARID, value)
-            if (err .ne. NF_ENOTVAR) 
+            err = nfmpi_put_var_$1_all(ncid, BAD_VARID, value)
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             nels = 1
             do 3, j = 1, var_rank(i)
@@ -518,9 +520,9 @@ define([TEST_NFMPI_PUT_VAR],dnl
 3           continue
             allInExtRange = .true.
             do 4, j = 1, var_nels(i)
-                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+                err = index2indexes(j, var_rank(i), var_shape(1,i),
      +                              index)
-                if (err .ne. NF_NOERR) 
+                if (err .ne. NF_NOERR)
      +              call error('error in index2indexes 1')
                 val = hash_$1(var_type(i), var_rank(i),
      +                        index, NFT_ITYPE($1))
@@ -529,7 +531,7 @@ define([TEST_NFMPI_PUT_VAR],dnl
                 allInExtRange = allInExtRange .and.
      +              inRange3(val, var_type(i), NFT_ITYPE($1))
 4           continue
-            err = nfmpi_put_var_$1(ncid, i, value)
+            err = nfmpi_put_var_$1_all(ncid, i, value)
             if (canConvert) then
                 if (allInExtRange) then
                     if (err .ne. NF_NOERR)
@@ -544,7 +546,6 @@ define([TEST_NFMPI_PUT_VAR],dnl
      +              call errore('wrong type: ', err)
             endif
 1       continue
-        err = nfmpi_end_indep_data(ncid)
 
 C       The preceeding has written nothing for record variables, now try
 C       again with more than 0 records.
@@ -556,10 +557,9 @@ C       Assumes variable cr is char vector with UNLIMITED dimension.
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_inq_varid: ', err)
         index(1) = NRECS
-        err = nfmpi_begin_indep_data(ncid)
-        err = nfmpi_put_var1_text(ncid, vid, index, 'x')
+        err = nfmpi_put_var1_text_all(ncid, vid, index, 'x')
         if (err .ne. NF_NOERR)
-     +      call errore('nfmpi_put_var1_text: ', err)
+     +      call errore('nfmpi_put_var1_text_all: ', err)
 
         do 5 i = 1, numVars
 C           Only test record variables here
@@ -571,7 +571,7 @@ C           Only test record variables here
      +              stop 'var_rank(i) .gt. MAX_RANK'
                 if (var_nels(i) .gt. MAX_NELS)
      +              stop 'var_nels(i) .gt. MAX_NELS'
-                err = nfmpi_put_var_$1(BAD_ID, i, value)
+                err = nfmpi_put_var_$1_all(BAD_ID, i, value)
 
                 nels = 1
                 do 6 j = 1, var_rank(i)
@@ -579,9 +579,9 @@ C           Only test record variables here
 6               continue
                 allInExtRange = .true.
                 do 7, j = 1, nels
-                    err = index2indexes(j, var_rank(i), var_shape(1,i), 
+                    err = index2indexes(j, var_rank(i), var_shape(1,i),
      +                              index)
-                    if (err .ne. NF_NOERR) 
+                    if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes()')
                     val = hash_$1(var_type(i), var_rank(i),
      +                            index, NFT_ITYPE($1))
@@ -590,7 +590,7 @@ C           Only test record variables here
                     allInExtRange = allInExtRange .and.
      +                  inRange3(val, var_type(i), NFT_ITYPE($1))
 7               continue
-                err = nfmpi_put_var_$1(ncid, i, value)
+                err = nfmpi_put_var_$1_all(ncid, i, value)
                 if (canConvert) then
                     if (allInExtRange) then
                         if (err .ne. NF_NOERR)
@@ -605,16 +605,15 @@ C           Only test record variables here
                 endif
             endif
 5       continue
-        err = nfmpi_end_indep_data(ncid)
         err = nfmpi_close(ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
 
         call check_vars_$1(scratch)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed: ', 
+     +      call errorc('delete of scratch file failed: ',
      +                  scratch)
         end
 ])dnl
@@ -675,97 +674,104 @@ define([TEST_NFMPI_PUT_VARA],dnl
 2           continue
             err = nfmpi_put_vara_$1_all(BAD_ID, i, start,
      +                  edge, value)
-            if (err .ne. NF_EBADID) 
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
             err = nfmpi_put_vara_$1_all(ncid, BAD_VARID,
      +                  start, edge, value)
-            if (err .ne. NF_ENOTVAR) 
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
-                    start(j) = var_shape(j,i) + 1
-                    err = nfmpi_put_vara_$1_all(ncid, i, start, 
-     +                                   edge, value)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EINVALCOORDS)
-     +                      call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nfmpi_put_vara_$1_all(ncid, i, start, 
-     +                                   edge, value)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EEDGE)
-     +                      call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_put_vara_$1_all(ncid, i, start,
+     +                                      edge, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_put_vara_$1_all(ncid, i, start,
+     +                                      edge, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
 3           continue
 
 C           /* Check correct error returned even when nothing to put */
-            do 20, j = 1, var_rank(i)
+            do 4, j = 1, var_rank(i)
                 edge(j) = 0
-20          continue
-            err = nfmpi_put_vara_$1_all(BAD_ID, i, start,
-     +          edge, value)
-            if (err .ne. NF_EBADID) 
+4           continue
+            err = nfmpi_put_vara_$1_all(BAD_ID, i,
+     +                                  start, edge, value)
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
             err = nfmpi_put_vara_$1_all(ncid, BAD_VARID,
-     +          start, edge, value)
-            if (err .ne. NF_ENOTVAR) 
+     +                                  start, edge, value)
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
-            do 21, j = 1, var_rank(i)
-                if (var_dimid(j,i) .gt. 1) then     ! skip record dim
-                    start(j) = var_shape(j,i) + 1
-                    err = nfmpi_put_vara_$1_all(ncid, i,
-     +                      start, edge, value)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EINVALCOORDS)
-     +                      call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_put_vara_$1_all(ncid, i,
+     +                                      start, edge, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF_NOERR)
+     +                  call errore('expect no error: ', err)
+#else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+#endif
                 endif
-21          continue
-
-! wkliao: this test below of put_vara is redundant and incorrectly uses the
-!         value[] set from the previously iteration. There is no such test
-!         in put_vars and put_varm.
-!
-!           err = nfmpi_put_vara_$1_all(ncid, i, start,
-!    +          edge, value)
-!           if (canConvert) then
-!               if (err .ne. NF_NOERR) 
-!    +              call error(nfmpi_strerror(err))
-!           else
-!               if (err .ne. NF_ECHAR)
-!    +              call errore('wrong type: ', err)
-!           endif
-
-            do 22, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 2
+                err = nfmpi_put_vara_$1_all(ncid, i,
+     +                                      start, edge, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nfmpi_put_vara_$1_all(ncid, i,
+     +                                  start, edge, value)
+            if (canConvert) then
+                if (err .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(err))
+            else
+                if (err .ne. NF_ECHAR)
+     +              call errore('wrong type: ', err)
+            endif
+            do 6, j = 1, var_rank(i)
                 edge(j) = 1
-22          continue
-
+6           continue
 
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
             !/* bits of k determine whether to put lower or upper part of dim */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nels = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -774,27 +780,27 @@ C           /* Check correct error returned even when nothing to put */
                         edge(j) = var_shape(j,i) - mid(j)
                     end if
                     nels = nels * int(edge(j))
-6               continue
+9               continue
                 allInExtRange = .true.
-                do 7, j = 1, nels
+                do 10, j = 1, nels
                     err = index2indexes(j, var_rank(i), edge, index)
-                    if (err .ne. NF_NOERR) 
+                    if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes 1')
-                    do 8, d = 1, var_rank(i)
+                    do 11, d = 1, var_rank(i)
                         index(d) = index(d) + start(d) - 1
-8                   continue
+11                  continue
                     val = hash_$1(var_type(i), var_rank(i),
      +                            index, NFT_ITYPE($1))
                     MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
                     val = ARITH3($1, value, j)
                     allInExtRange = allInExtRange .and.
      +                  inRange3(val, var_type(i), NFT_ITYPE($1))
-7               continue
+10              continue
                 err = nfmpi_put_vara_$1_all(ncid, i, start,
      +                  edge, value)
                 if (canConvert) then
                     if (allInExtRange) then
-                        if (err .ne. NF_NOERR) 
+                        if (err .ne. NF_NOERR)
      +                      call error(nfmpi_strerror(err))
                     else
                         if (err .ne. NF_ERANGE)
@@ -804,18 +810,18 @@ C           /* Check correct error returned even when nothing to put */
                     if (nels .gt. 0 .and. err .ne. NF_ECHAR)
      +                  call errore('wrong type: ', err)
                 end if
-5           continue
+8           continue
 1       continue
 
         err = nfmpi_close(ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
 
         call check_vars_$1(scratch)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed: ', 
+     +      call errorc('delete of scratch file failed: ',
      +          scratch)
         end
 ])dnl
@@ -883,65 +889,108 @@ define([TEST_NFMPI_PUT_VARS],dnl
 2           continue
             err = nfmpi_put_vars_$1_all(BAD_ID, i, start,
      +                  edge, stride, value)
-            if (err .ne. NF_EBADID) 
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
             err = nfmpi_put_vars_$1_all(ncid, BAD_VARID, start,
-     +                           edge, stride, 
+     +                           edge, stride,
      +                           value)
-            if (err .ne. NF_ENOTVAR) 
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    ! skip record dim
-                    start(j) = var_shape(j,i) + 1
-                    err = nfmpi_put_vars_$1_all(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   value)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EINVALCOORDS)
-     +                          call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nfmpi_put_vars_$1_all(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   value)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EEDGE)
-     +                      call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                    stride(j) = 0
-                    err = nfmpi_put_vars_$1_all(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   value)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_ESTRIDE)
-     +                      call errore('bad stride: ', err)
-                    endif
-                    stride(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_put_vars_$1_all(ncid, i, start,
+     +                                      edge, stride, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_put_vars_$1_all(ncid, i, start,
+     +                                      edge, stride, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nfmpi_put_vars_$1_all(ncid, i, start,
+     +                                      edge, stride, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_ESTRIDE)
+     +                  call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
 3           continue
+C           /* Check correct error returned even when nothing to put */
+            do 4, j = 1, var_rank(i)
+                edge(j) = 0
+4           continue
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_put_vars_$1_all(ncid, i,
+     +                                      start, edge, stride, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF_NOERR)
+     +                  call errore('expect no error: ', err)
+#else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+#endif
+                endif
+                start(j) = var_shape(j,i) + 2
+                err = nfmpi_put_vars_$1_all(ncid, i,
+     +                                      start, edge, stride, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nfmpi_put_vars_$1_all(ncid, i,
+     +                                  start, edge, stride, value)
+            if (canConvert) then
+                if (err .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(err))
+            else
+                if (err .ne. NF_ECHAR)
+     +              call errore('wrong type: ', err)
+            endif
+            do 6, j = 1, var_rank(i)
+                edge(j) = 1
+6           continue
+
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
             !/* bits of k determine whether to put lower or upper part of dim */
             !/* choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -956,17 +1005,17 @@ define([TEST_NFMPI_PUT_VARS],dnl
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * INT(stride(j))
-6               continue
-                do 7, m = 1, nstarts
+9               continue
+                do 10, m = 1, nstarts
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) / stride(j)
                         nels = nels * int(count(j))
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
                     !/* Random choice of forward or backward */
 C/* TODO
 C                   if ( roll(2) ) {
@@ -977,29 +1026,29 @@ C                       }
 C                   }
 C*/
                     allInExtRange = .true.
-                    do 9, j = 1, nels
-                        err = index2indexes(j, var_rank(i), count, 
+                    do 12, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count,
      +                                      index2)
                         if (err .ne. NF_NOERR)
      +                      call error('error in index2indexes')
-                        do 10, d = 1, var_rank(i)
-                            index2(d) = index(d) + 
+                        do 13, d = 1, var_rank(i)
+                            index2(d) = index(d) +
      +                                  (index2(d)-1) * stride(d)
-10                      continue
+13                      continue
                         val = hash_$1(var_type(i), var_rank(i),
      +                                index2, NFT_ITYPE($1))
                         MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
                         val = ARITH3($1, value, j)
                         allInExtRange = allInExtRange .and.
-     +                      inRange3(val, var_type(i), 
+     +                      inRange3(val, var_type(i),
      +                               NFT_ITYPE($1))
-9                   continue
+12                  continue
                     err = nfmpi_put_vars_$1_all(ncid, i, index,
      +                                   count, stride,
      +                                   value)
                     if (canConvert) then
                         if (allInExtRange) then
-                            if (err .ne. NF_NOERR) 
+                            if (err .ne. NF_NOERR)
      +                          call error(nfmpi_strerror(err))
                         else
                             if (err .ne. NF_ERANGE)
@@ -1009,19 +1058,19 @@ C*/
                         if (nels .gt. 0 .and. err .ne. NF_ECHAR)
      +                      call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 1       continue
 
         err = nfmpi_close(ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
 
         call check_vars_$1(scratch)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed:', 
+     +      call errorc('delete of scratch file failed:',
      +          scratch)
         end
 ])dnl
@@ -1091,68 +1140,109 @@ define([TEST_NFMPI_PUT_VARM],dnl
                 stride(j) = 1
                 imap(j) = 1
 2           continue
-            err = nfmpi_put_varm_$1_all(BAD_ID, i, start,
-     +                           edge, stride, imap, 
-     +                           value)
-            if (err .ne. NF_EBADID) 
+            err = nfmpi_put_varm_$1_all(BAD_ID, i,
+     +            start, edge, stride, imap, value)
+            if (err .ne. NF_EBADID)
      +          call errore('bad ncid: ', err)
-            err = nfmpi_put_varm_$1_all(ncid, BAD_VARID, start,
-     +                           edge, stride, 
-     +                           imap, value)
-            if (err .ne. NF_ENOTVAR) 
+            err = nfmpi_put_varm_$1_all(ncid, BAD_VARID,
+     +            start, edge, stride, imap, value)
+            if (err .ne. NF_ENOTVAR)
      +          call errore('bad var id: ', err)
             do 3, j = 1, var_rank(i)
-                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
-                    start(j) = var_shape(j,i) + 1
-                    err = nfmpi_put_varm_$1_all(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   imap, value)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EINVALCOORDS)
-     +                      call errore('bad start: ', err)
-                    endif
-                    start(j) = 1
-                    edge(j) = var_shape(j,i) + 1
-                    err = nfmpi_put_varm_$1_all(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   imap, value)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_EEDGE)
-     +                      call errore('bad edge: ', err)
-                    endif
-                    edge(j) = 1
-                    stride(j) = 0
-                    err = nfmpi_put_varm_$1_all(ncid, i, start,
-     +                                   edge, stride, 
-     +                                   imap, value)
-                    if (.not. canConvert) then
-                        if (err .ne. NF_ECHAR)
-     +                      call errore('conversion: ', err)
-                    else
-                        if (err .ne. NF_ESTRIDE)
-     +                      call errore('bad stride: ', err)
-                    endif
-                    stride(j) = 1
-                end if
+                if (var_dimid(j,i) .EQ. RECDIM) goto 3 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_put_varm_$1_all(ncid, i,
+     +                start, edge, stride, imap, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_put_varm_$1_all(ncid, i,
+     +                start, edge, stride, imap, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nfmpi_put_varm_$1_all(ncid, i,
+     +                start, edge, stride, imap, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_ESTRIDE)
+     +                  call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
 3           continue
+C           /* Check correct error returned even when nothing to put */
+            do 4, j = 1, var_rank(i)
+                edge(j) = 0
+4           continue
+            do 5, j = 1, var_rank(i)
+                if (var_dimid(j,i) .EQ. RECDIM) goto 5 ! skip record dim
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_put_varm_$1_all(ncid, i,
+     +                start, edge, stride, imap, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+#ifdef RELAX_COORD_BOUND
+                    if (err .ne. NF_NOERR)
+     +                  call errore('expect no error: ', err)
+#else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+#endif
+                endif
+                start(j) = var_shape(j,i) + 2
+                err = nfmpi_put_varm_$1_all(ncid, i,
+     +                start, edge, stride, imap, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad start: ', err)
+                endif
+                start(j) = 1
+5           continue
+            MAKE_TYPE2($1, value, 0)
+            err = nfmpi_put_varm_$1_all(ncid, i,
+     +            start, edge, stride, imap, value)
+            if (canConvert) then
+                if (err .ne. NF_NOERR)
+     +              call error(nfmpi_strerror(err))
+            else
+                if (err .ne. NF_ECHAR)
+     +              call errore('wrong type: ', err)
+            endif
+            do 6, j = 1, var_rank(i)
+                edge(j) = 1
+6           continue
+
             !/* Choose a random point dividing each dim into 2 parts */
             !/* Put 2^rank (nslabs) slabs so defined */
             nslabs = 1
-            do 4, j = 1, var_rank(i)
+            do 7, j = 1, var_rank(i)
                 mid(j) = roll( var_shape(j,i) )
                 nslabs = nslabs * 2
-4           continue
+7           continue
             !/* bits of k determine whether to put lower or upper part of dim */
             !/* choose random stride from 1 to edge */
-            do 5, k = 1, nslabs
+            do 8, k = 1, nslabs
                 nstarts = 1
-                do 6, j = 1, var_rank(i)
+                do 9, j = 1, var_rank(i)
                     if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
                         start(j) = 1
                         edge(j) = mid(j)
@@ -1167,51 +1257,51 @@ define([TEST_NFMPI_PUT_VARM],dnl
                     end if
                     sstride(j) = stride(j)
                     nstarts = nstarts * INT(stride(j))
-6               continue
-                do 7, m = 1, nstarts
+9               continue
+                do 10, m = 1, nstarts
                     err = index2indexes(m, var_rank(i), sstride, index)
                     if (err .ne. NF_NOERR)
      +                  call error('error in index2indexes')
                     nels = 1
-                    do 8, j = 1, var_rank(i)
+                    do 11, j = 1, var_rank(i)
                         count(j) = 1 + (edge(j) - index(j)) / stride(j)
                         nels = nels * int(count(j))
                         index(j) = index(j) + start(j) - 1
-8                   continue
+11                  continue
                     !/* Random choice of forward or backward */
 C/* TODO
 C                   if ( roll(2) ) then
-C                       do 9, j = 1, var_rank(i)
-C                           index(j) = index(j) + 
+C                       do 12, j = 1, var_rank(i)
+C                           index(j) = index(j) +
 C     +                         (count(j) - 1) * stride(j)
 C                           stride(j) = -stride(j)
-C9                      continue
+C12                     continue
 C                   end if
 C*/
                     if (var_rank(i) .gt. 0) then
                         imap(1) = 1
-                        do 10, j = 2, var_rank(i)
+                        do 13, j = 2, var_rank(i)
                             imap(j) = imap(j-1) * count(j-1)
-10                      continue
+13                      continue
                     end if
                     allInExtRange = .true.
-                    do 11 j = 1, nels
-                        err = index2indexes(j, var_rank(i), count, 
+                    do 14 j = 1, nels
+                        err = index2indexes(j, var_rank(i), count,
      +                                      index2)
                         if (err .ne. NF_NOERR)
      +                      call error('error in index2indexes')
-                        do 12, d = 1, var_rank(i)
-                            index2(d) = index(d) + 
+                        do 15, d = 1, var_rank(i)
+                            index2(d) = index(d) +
      +                          (index2(d)-1) * stride(d)
-12                      continue
-                        val = hash_$1(var_type(i),var_rank(i), 
+15                      continue
+                        val = hash_$1(var_type(i),var_rank(i),
      +                                index2, NFT_ITYPE($1))
                         MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
                         val = ARITH3($1, value, j)
                         allInExtRange = allInExtRange .and.
-     +                      inRange3(val, var_type(i), 
+     +                      inRange3(val, var_type(i),
      +                               NFT_ITYPE($1))
-11                  continue
+14                  continue
                     err = nfmpi_put_varm_$1_all(ncid,i,index,count,
      +                                   stride,imap,
      +                                   value)
@@ -1227,19 +1317,19 @@ C*/
                         if (nels .gt. 0 .and. err .ne. NF_ECHAR)
      +                      call errore('wrong type: ', err)
                     end if
-7               continue
-5           continue
+10              continue
+8           continue
 1       continue
 
         err = nfmpi_close(ncid)
-        if (err .ne. NF_NOERR) 
+        if (err .ne. NF_NOERR)
      +      call errore('nfmpi_close: ', err)
 
         call check_vars_$1(scratch)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed:', 
+     +      call errorc('delete of scratch file failed:',
      +          scratch)
         end
 ])dnl
@@ -1285,18 +1375,18 @@ define([TEST_NFMPI_PUT_ATT],dnl
                     if (.not.((ATT_LEN_LL .le. MAX_NELS)))
      +                  stop 'assert(ATT_LEN_LL .le. MAX_NELS)'
                     err = nfmpi_put_att_$1(BAD_ID, i,
-     +                                  ATT_NAME(j,i), 
-     +                                  ATT_TYPE(j,i), 
+     +                                  ATT_NAME(j,i),
+     +                                  ATT_TYPE(j,i),
      +                                  ATT_LEN_LL, value)
                     if (err .ne. NF_EBADID)
      +                  call errore('bad ncid: ', err)
                     err = nfmpi_put_att_$1(ncid, BAD_VARID,
-     +                  ATT_NAME(j,i), 
+     +                  ATT_NAME(j,i),
      +                  ATT_TYPE(j,i), ATT_LEN_LL, value)
                     if (err .ne. NF_ENOTVAR)
      +                  call errore('bad var id: ', err)
                     err = nfmpi_put_att_$1(ncid, i,
-     +                  ATT_NAME(j,i), BAD_TYPE, 
+     +                  ATT_NAME(j,i), BAD_TYPE,
      +                  ATT_LEN_LL, value)
                     if (err .ne. NF_EBADTYPE)
      +                  call errore('bad type: ', err)
@@ -1308,11 +1398,11 @@ define([TEST_NFMPI_PUT_ATT],dnl
                         MAKE_TYPE2($1, VAR_ELEM($1, value, k), val)
                         val = ARITH3($1, value, k)
                         allInExtRange = allInExtRange .and.
-     +                      inRange3(val, ATT_TYPE(j,i), 
+     +                      inRange3(val, ATT_TYPE(j,i),
      +                               NFT_ITYPE($1))
 3                   continue
-                    err = nfmpi_put_att_$1(ncid, i, ATT_NAME(j,i), 
-     +                                  ATT_TYPE(j,i), ATT_LEN_LL, 
+                    err = nfmpi_put_att_$1(ncid, i, ATT_NAME(j,i),
+     +                                  ATT_TYPE(j,i), ATT_LEN_LL,
      +                                  value)
                     if (allInExtRange) then
                         if (err .ne. NF_NOERR)
@@ -1332,20 +1422,12 @@ define([TEST_NFMPI_PUT_ATT],dnl
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed:', 
+     +      call errorc('delete of scratch file failed:',
      +          scratch)
         end
 ])dnl
 
-divert(0)dnl
-dnl If you see this line, you can ignore the next one.
-C Do not edit this file. It is produced from the corresponding .m4 source */
-
-C********************************************************************
-C   Copyright 1996, UCAR/Unidata
-C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
-C   $Id: test_put.m4 2232 2015-12-16 22:16:52Z wkliao $
-C********************************************************************
+dnl divert(0)dnl
 
 HASH(text)
 #ifdef NF_INT1_T
@@ -1478,8 +1560,8 @@ TEST_NFMPI_PUT_VARM(double)
      +                  ATT_NAME(j,i), ATT_LEN_LL, value)
                     if (err .ne. NF_EBADID)
      +                  call errore('bad ncid: ', err)
-                    err = nfmpi_put_att_text(ncid, BAD_VARID, 
-     +                                    ATT_NAME(j,i), 
+                    err = nfmpi_put_att_text(ncid, BAD_VARID,
+     +                                    ATT_NAME(j,i),
      +                                    ATT_LEN_LL, value)
                     if (err .ne. NF_ENOTVAR)
      +                  call errore('bad var id: ', err)
@@ -1487,7 +1569,7 @@ TEST_NFMPI_PUT_VARM(double)
                         value(k:k) = char(int(hash(ATT_TYPE(j,i),
      +                                             -1, k)))
 3                   continue
-                    err = nfmpi_put_att_text(ncid, i, ATT_NAME(j,i), 
+                    err = nfmpi_put_att_text(ncid, i, ATT_NAME(j,i),
      +                  ATT_LEN_LL, value)
                     if (err .ne. NF_NOERR)
      +                  call error(nfmpi_strerror(err))
@@ -1502,7 +1584,7 @@ TEST_NFMPI_PUT_VARM(double)
 
         err = nfmpi_delete(scratch, info)
         if (err .ne. NF_NOERR)
-     +      call errorc('delete of scratch file failed:', 
+     +      call errorc('delete of scratch file failed:',
      +          scratch)
         end
 
diff --git a/test/nf_test/test_read.F b/test/nf_test/test_read.F
index b4355b6..b79ce82 100644
--- a/test/nf_test/test_read.F
+++ b/test/nf_test/test_read.F
@@ -1,7 +1,7 @@
 C*********************************************************************
 C   Copyright 1996, UCAR/Unidata
 C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
-C   $Id: test_read.F 2296 2016-01-06 21:19:36Z wkliao $
+C   $Id: test_read.F 2474 2016-09-05 23:13:05Z wkliao $
 C*********************************************************************
 
 C Test nfmpi_strerror.
@@ -134,17 +134,19 @@ C On exit, any open netCDF files are closed.
 
         nok = 0
 
-!       Try to open a nonexistent file, this call should fail
+C       Try to open a nonexistent file, this call should fail
         err = nfmpi_open(comm, 'tooth-fairy.nc', NF_NOWRITE, info, ncid)
 
-!       On some systems, opening an nonexisting file will actually create the
-!       file. In this case, we print the error messages on screen and move on
-!       to the next test, instead of aborting the entire test.
+C       On some systems, opening an nonexisting file will actually create the
+C       file. In this case, we print the error messages on screen and move on
+C       to the next test, instead of aborting the entire test.
 
         if (err .eq. NF_NOERR) then
             print*,
      +    'opening a nonexistent file expects to fail, but got NF_NOERR'
-        elseif (err .ne. NF_ENOENT) then
+        elseif (err .ne. NF_ENOENT .AND. err .ne. NF_EFILE) then
+C           older version of OpenMPI and MPICH may return MPI_ERR_IO instead
+C           of MPI_ERR_NO_SUCH_FILE
             print*,
      +    'opening a nonexistent file expects NF_ENOENT, but got ',err
         else
@@ -575,10 +577,7 @@ C               /* Make sure nfmpi_inq stills sees additions in data mode */
         include "pnetcdf.inc"
 #include "tests.inc"
 
-        integer ncid
-        integer unlimdim
-        integer err
-        integer nok
+        integer ncid, unlimdim, flags, err, nok
 
         nok = 0
 
@@ -588,6 +587,36 @@ C               /* Make sure nfmpi_inq stills sees additions in data mode */
         else
             nok = nok + 1
         endif
+
+        if (.not. readonly) then        !/* tests using netCDF scratch file */
+            flags = IOR(NF_CLOBBER, extra_flags)
+            err = nfmpi_create(comm, scratch, flags, info, ncid)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_create: ', err)
+            else
+                err = nfmpi_inq_unlimdim(ncid, unlimdim)
+                if (err .ne. NF_NOERR) then
+                    call errore('nfmpi_inq_unlimdim: ', err)
+                else
+                    if (unlimdim .NE. -1) then
+                        call errori
+     +                  ('nfmpi_inq_unlimdim: wrong number returned, ',
+     +                  unlimdim)
+                        print *, 'expected -1'
+                    else
+                        nok = nok + 1
+                    endif
+                endif
+                err = nfmpi_close(ncid)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_close: ', err)
+                err = nfmpi_delete(scratch, info)
+                if (err .ne. NF_NOERR) 
+     +              call errorc('delete of scratch file failed: ',
+     +                          scratch)
+            endif
+        endif
+
         err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
         if (err .ne. NF_NOERR)
      +      call errore('nfmpi_open: ', err)
diff --git a/test/nf_test/tests.inc.in b/test/nf_test/tests.inc.in
index 9bcd322..50c0222 100644
--- a/test/nf_test/tests.inc.in
+++ b/test/nf_test/tests.inc.in
@@ -2,7 +2,9 @@
 !  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-!  $Id: tests.inc.in 2289 2016-01-02 08:26:40Z wkliao $
+!  $Id: tests.inc.in 2615 2016-11-13 23:58:41Z wkliao $
+!
+! @configure_input@
 !
 
 !!!!
diff --git a/test/nf_test/util.F b/test/nf_test/util.F
index 834449d..1c99c46 100644
--- a/test/nf_test/util.F
+++ b/test/nf_test/util.F
@@ -1,7 +1,7 @@
 !*********************************************************************
 !   Copyright 1996, UCAR/Unidata
 !   See netcdf/COPYRIGHT file for copying and redistribution conditions.
-!   $Id: util.F 2284 2015-12-30 20:27:18Z wkliao $
+!   $Id: util.F 2527 2016-10-09 05:00:49Z wkliao $
 !********************************************************************/
 
       SUBROUTINE PRINT_NOK(NOK)
@@ -517,20 +517,18 @@
 
 
 ! wrapper for hash to handle special NC_BYTE/uchar adjustment */
-      double precision function hash4(type, rank, index, itype)
+      double precision function hash4(type, rank, index)
       implicit  none
-      integer   type
-      integer   rank
       include "pnetcdf.inc"
 #include "tests.inc"
-      double precision hash
 
+      integer   type
+      integer   rank
       integer*8 index(*)
-      integer   itype
+      double precision hash
+
+      hash4 = hash(type, rank, index)
 
-      hash4 = hash( type, rank, index )
-      if ((itype .eq. NFT_CHAR) .and. (type .eq. NF_BYTE) .and. 
-     +    (hash4 .ge. -128) .and. (hash4 .lt. 0)) hash4 = hash4 + 256
       end
 
 
diff --git a/test/nonblocking/Makefile.in b/test/nonblocking/Makefile.in
index c157254..f038bf1 100644
--- a/test/nonblocking/Makefile.in
+++ b/test/nonblocking/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2318 2016-02-04 00:18:26Z wkliao $
+# $Id: Makefile.in 2590 2016-10-31 21:37:02Z wkliao $
 #
 # @configure_input@
 
@@ -15,9 +15,6 @@ INCLUDES  = -I../../src/lib -I$(srcdir)/../common
 FPPFLAGS += -I../../src/libf @FC_MODINC at ../../src/libf90 @FC_MODINC at ../common
 LDFLAGS  := -L../common $(LDFLAGS)
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
-ifeq (@PNC_DEBUG@, yes)
-CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
-endif
 
 C_SRCS   = mcoll_perf.c \
            test_bput.c \
diff --git a/test/nonblocking/bput_varn_uint.c b/test/nonblocking/bput_varn_uint.c
index 7ec48d2..bfb3b71 100644
--- a/test/nonblocking/bput_varn_uint.c
+++ b/test/nonblocking/bput_varn_uint.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: bput_varn_uint.c 2219 2015-12-11 22:30:03Z wkliao $ */
+/* $Id: bput_varn_uint.c 2400 2016-04-18 22:25:13Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example tests nonblocking buffered write varn APIs, including
@@ -31,28 +31,28 @@
  *    data:
  *
  *     var0 =
- *      3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
- *      0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
- *      1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
- *      0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
- *
+ *      13, 13, 13, 11, 11, 10, 10, 12, 11, 11,
+ *      10, 12, 12, 12, 13, 11, 11, 12, 12, 12,
+ *      11, 11, 12, 13, 13, 13, 10, 10, 11, 11,
+ *      10, 10, 10, 12, 11, 11, 11, 13, 13, 13 ;
  *     var1 =
- *      2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
- *      3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
- *      0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
- *      3, 3, 3, 1, 0, 0, 0, 2, 2, 2 ;
+ *      12, 12, 12, 10, 10, 13, 13, 11, 10, 10,
+ *      13, 11, 11, 11, 12, 10, 10, 11, 11, 11,
+ *      10, 10, 11, 12, 12, 12, 13, 13, 10, 10,
+ *      13, 13, 13, 11, 10, 10, 10, 12, 12, 12 ;
+
  *
  *     var2 =
- *      1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
- *      2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
- *      3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
- *      2, 2, 2, 0, 3, 3, 3, 1, 1, 1 ;
+ *      11, 11, 11, 13, 13, 12, 12, 10, 13, 13,
+ *      12, 10, 10, 10, 11, 13, 13, 10, 10, 10,
+ *      13, 13, 10, 11, 11, 11, 12, 12, 13, 13,
+ *      12, 12, 12, 10, 13, 13, 13, 11, 11, 11 ;
  *
  *     var3 =
- *      0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
- *      1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
- *      2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
- *      1, 1, 1, 3, 2, 2, 2, 0, 0, 0 ;
+ *      10, 10, 10, 12, 12, 11, 11, 13, 12, 12,
+ *      11, 13, 13, 13, 10, 12, 12, 13, 13, 13,
+ *      12, 12, 13, 10, 10, 10, 11, 11, 12, 12,
+ *      11, 11, 11, 13, 12, 12, 12, 10, 10, 10 ;
  *    }
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -106,22 +106,22 @@ int check_contents_for_fail(int ncid, int *varid)
 {
     /* all processes read entire variables back and check contents */
     int i, j, err, nprocs;
-    unsigned int expected[4][NY*NX] = {{3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
-                                        0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
-                                        1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
-                                        0, 0, 0, 2, 1, 1, 1, 3, 3, 3},
-                                       {2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
-                                        3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
-                                        0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
-                                        3, 3, 3, 1, 0, 0, 0, 2, 2, 2},
-                                       {1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
-                                        2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
-                                        3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
-                                        2, 2, 2, 0, 3, 3, 3, 1, 1, 1},
-                                       {0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
-                                        1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
-                                        2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
-                                        1, 1, 1, 3, 2, 2, 2, 0, 0, 0}};
+    unsigned int expected[4][NY*NX] = {{13, 13, 13, 11, 11, 10, 10, 12, 11, 11,
+                                        10, 12, 12, 12, 13, 11, 11, 12, 12, 12,
+                                        11, 11, 12, 13, 13, 13, 10, 10, 11, 11,
+                                        10, 10, 10, 12, 11, 11, 11, 13, 13, 13},
+                                       {12, 12, 12, 10, 10, 13, 13, 11, 10, 10,
+                                        13, 11, 11, 11, 12, 10, 10, 11, 11, 11,
+                                        10, 10, 11, 12, 12, 12, 13, 13, 10, 10,
+                                        13, 13, 13, 11, 10, 10, 10, 12, 12, 12},
+                                       {11, 11, 11, 13, 13, 12, 12, 10, 13, 13,
+                                        12, 10, 10, 10, 11, 13, 13, 10, 10, 10,
+                                        13, 13, 10, 11, 11, 11, 12, 12, 13, 13,
+                                        12, 12, 12, 10, 13, 13, 13, 11, 11, 11},
+                                       {10, 10, 10, 12, 12, 11, 11, 13, 12, 12,
+                                        11, 13, 13, 13, 10, 12, 12, 13, 13, 13,
+                                        12, 12, 13, 10, 10, 10, 11, 11, 12, 12,
+                                        11, 11, 11, 13, 12, 12, 12, 10, 10, 10}};
 
     unsigned int *r_buffer = (unsigned int*) malloc(NY*NX * sizeof(unsigned int));
 
@@ -334,7 +334,7 @@ int main(int argc, char** argv)
 
         /* allocate I/O buffer and initialize its contents */
         buffer[i] = (unsigned int*) malloc(req_lens[i] * sizeof(unsigned int));
-        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank;
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank+10;
         bufsize += req_lens[i];
     }
     bufsize *= sizeof(unsigned int);
@@ -353,13 +353,22 @@ int main(int argc, char** argv)
         nerrs++;
     }
 
-    /* write usning varn API, one bput call per variable */
+    /* write using varn API, one bput call per variable */
     clear_file_contents(ncid, varid);
     for (i=0; i<nreqs; i++) {
         err = ncmpi_bput_varn_uint(ncid, varid[i], my_nsegs[i], starts[i],
                                    counts[i], buffer[i], &reqs[i]);
         ERR
     }
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%u\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
     nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
     check_attached_buffer_usage(ncid, bufsize, bufsize, __LINE__);
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
@@ -385,6 +394,15 @@ int main(int argc, char** argv)
                                    counts[i], buffer[i], &reqs[i]);
         ERR
     }
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%u\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
     nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
     check_attached_buffer_usage(ncid, bufsize, bufsize, __LINE__);
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
@@ -404,18 +422,36 @@ int main(int argc, char** argv)
         MPI_Type_vector(req_lens[i], 1, 2, MPI_UNSIGNED, &buftype);
         MPI_Type_commit(&buftype);
         buffer[i] = (unsigned int*)malloc(req_lens[i]*2*sizeof(unsigned int));
-        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank+10;
 
         err = ncmpi_bput_varn(ncid, varid[i], my_nsegs[i], starts[i],
                               counts[i], buffer[i], 1, buftype, &reqs[i]);
         ERR
         MPI_Type_free(&buftype);
     }
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]*2; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%u\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
     nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
     check_attached_buffer_usage(ncid, bufsize, bufsize, __LINE__);
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]*2; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%u\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
     check_attached_buffer_usage(ncid, bufsize, 0, __LINE__);
 
     /* all processes read entire variables back and check contents */
@@ -434,18 +470,36 @@ int main(int argc, char** argv)
         MPI_Datatype buftype;
         MPI_Type_vector(req_lens[i], 1, 2, MPI_UNSIGNED, &buftype);
         MPI_Type_commit(&buftype);
-        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank+10;
 
         err = ncmpi_bput_varn(ncid, varid[i], my_nsegs[i], starts[i],
                               counts[i], buffer[i], 1, buftype, &reqs[i]);
         ERR
         MPI_Type_free(&buftype);
     }
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]*2; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%u\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
     nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
     check_attached_buffer_usage(ncid, bufsize, bufsize, __LINE__);
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]*2; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%u\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
     check_attached_buffer_usage(ncid, bufsize, 0, __LINE__);
 
     /* all processes read entire variables back and check contents */
diff --git a/test/nonblocking/column_wise.c b/test/nonblocking/column_wise.c
index cea39e4..1fb7573 100644
--- a/test/nonblocking/column_wise.c
+++ b/test/nonblocking/column_wise.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: column_wise.c 2216 2015-12-08 05:47:19Z wkliao $ */
+/* $Id: column_wise.c 2404 2016-04-20 17:45:34Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example tests a number of nonblocking API calls, each writes a single
@@ -45,16 +45,16 @@
  *    data:
  *
  *     var =
- *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
- *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
- *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
- *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
- *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
- *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
- *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
- *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
- *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
- *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 ;
+ *      10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13,
+ *      10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13,
+ *      10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13,
+ *      10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13,
+ *      10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13,
+ *      10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13,
+ *      10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13,
+ *      10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13,
+ *      10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13,
+ *      10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13 ;
  *    }
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -130,7 +130,7 @@ int main(int argc, char** argv)
        by allocatsing buffersd separately */
     for (i=0; i<myNX; i++) {
         buf[i] = (int*) malloc(NY * sizeof(int));
-        for (j=0; j<NY; j++) buf[i][j] = rank;
+        for (j=0; j<NY; j++) buf[i][j] = rank+10;
     }
 
     reqs = (int*) malloc(myNX * sizeof(int));
@@ -147,9 +147,62 @@ int main(int argc, char** argv)
         ERR
         start[1] += nprocs;
     }
+
+    /* try re-order the request list */
+    for (i=0; i<myNX/2; i++) {
+        int tmp = reqs[2*i];
+        reqs[2*i] = reqs[2*i+1];
+        reqs[2*i+1] = tmp;
+    }
+
+    /* test cancelling requests and see if the user write buffer is properly
+     * byte-swapped back to it original form. To do this test, NY must be
+     * changed to use a number > NC_BYTE_SWAP_BUFFER_SIZE/sizeof(int), say
+     * 1025
+     */
+    err = ncmpi_cancel(ncid, num_reqs, reqs, sts);
+    ERR
+
+    /* check if write buffer contents have been altered after cancelling */
+    for (i=0; i<myNX; i++) {
+        for (j=0; j<NY; j++) {
+            if (buf[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%d\n", i,j,buf[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
+    /* post iput requests again */
+    start[1] = rank;
+    num_reqs = 0;
+    for (i=0; i<myNX; i++) {
+        err = ncmpi_iput_vara_int(ncid, varid, start, count, buf[i],
+                                  &reqs[num_reqs++]);
+        ERR
+        start[1] += nprocs;
+    }
+
+    /* try re-order the request list */
+    for (i=0; i<myNX/2; i++) {
+        int tmp = reqs[2*i];
+        reqs[2*i] = reqs[2*i+1];
+        reqs[2*i+1] = tmp;
+    }
+
     err = ncmpi_wait_all(ncid, num_reqs, reqs, sts);
     ERR
 
+    /* check if write buffer contents have been altered after wait */
+    for (i=0; i<myNX; i++) {
+        for (j=0; j<NY; j++) {
+            if (buf[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%d\n", i,j,buf[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
     /* check status of all requests */
     for (i=0; i<num_reqs; i++) {
         if (reqs[i] != NC_REQ_NULL) { /* add in PnetCDF v1.7.0 */
@@ -178,6 +231,19 @@ int main(int argc, char** argv)
         ERR
         start[1] += nprocs;
     }
+    /* this test is to see if cancelling free up all the internal malloc */
+    err = ncmpi_cancel(ncid, num_reqs, reqs, sts);
+    ERR
+
+    /* post iget requests again */
+    start[1] = rank;
+    num_reqs = 0;
+    for (i=0; i<myNX; i++) {
+        err = ncmpi_iget_vara_int(ncid, varid, start, count, buf[i],
+                                  &reqs[num_reqs++]);
+        ERR
+        start[1] += nprocs;
+    }
     err = ncmpi_wait_all(ncid, num_reqs, reqs, sts);
     ERR
 
@@ -191,8 +257,8 @@ int main(int argc, char** argv)
 
     for (i=0; i<myNX; i++) {
         for (j=0; j<NY; j++)
-            if (buf[i][j] != rank) {
-                printf("Error: expect buf[%d][%d]=%d but got %d\n",i,j,rank,buf[i][j]);
+            if (buf[i][j] != rank+10) {
+                printf("Error: expect buf[%d][%d]=%d but got %d\n",i,j,rank+10,buf[i][j]);
                 nerrs++;
             }
     }
diff --git a/test/nonblocking/flexible_bput.c b/test/nonblocking/flexible_bput.c
index 2f32dfa..4d094c3 100644
--- a/test/nonblocking/flexible_bput.c
+++ b/test/nonblocking/flexible_bput.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: flexible_bput.c 2134 2015-10-03 04:24:18Z wkliao $ */
+/* $Id: flexible_bput.c 2400 2016-04-18 22:25:13Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *
@@ -187,10 +187,13 @@ int main(int argc, char** argv)
     err = ncmpi_bput_varm(ncid, varid, start, count, stride, imap, buf_int,
                           1, subarray, &req);
     ERR
+    /* check if the contents of put buffer are altered */
+    CHECK_PUT_BUF(buf_int)
+
     err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
     err = status; ERR
 
-    /* check the contents of put buffer */
+    /* check the contents of put buffer are altered */
     CHECK_PUT_BUF(buf_int)
 
     err = ncmpi_buffer_detach(ncid); ERR
@@ -224,10 +227,14 @@ int main(int argc, char** argv)
     err = ncmpi_bput_varm(ncid, varid, start, count, stride, imap, buf_dbl,
                           1, subarray, &req);
     ERR
+
+    /* check the contents of put buffer are altered */
+    CHECK_PUT_BUF(buf_dbl)
+
     err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
     err = status; ERR
 
-    /* check the contents of put buffer */
+    /* check the contents of put buffer are altered */
     CHECK_PUT_BUF(buf_dbl)
 
     err = ncmpi_buffer_detach(ncid); ERR
diff --git a/test/nonblocking/i_varn_indef.c b/test/nonblocking/i_varn_indef.c
index 18093ba..34ee753 100644
--- a/test/nonblocking/i_varn_indef.c
+++ b/test/nonblocking/i_varn_indef.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: i_varn_indef.c 2318 2016-02-04 00:18:26Z wkliao $ */
+/* $Id: i_varn_indef.c 2400 2016-04-18 22:25:13Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example tests posting nonblocking varn APIs, including
@@ -32,28 +32,28 @@
  *    data:
  *
  *     var0 =
- *      3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
- *      0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
- *      1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
- *      0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *      13, 13, 13, 11, 11, 10, 10, 12, 11, 11,
+ *      10, 12, 12, 12, 13, 11, 11, 12, 12, 12,
+ *      11, 11, 12, 13, 13, 13, 10, 10, 11, 11,
+ *      10, 10, 10, 12, 11, 11, 11, 13, 13, 13 ;
  *
  *     var1 =
- *      2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
- *      3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
- *      0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
- *      3, 3, 3, 1, 0, 0, 0, 2, 2, 2 ;
+ *      12, 12, 12, 10, 10, 13, 13, 11, 10, 10,
+ *      13, 11, 11, 11, 12, 10, 10, 11, 11, 11,
+ *      10, 10, 11, 12, 12, 12, 13, 13, 10, 10,
+ *      13, 13, 13, 11, 10, 10, 10, 12, 12, 12 ;
  *
  *     var2 =
- *      1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
- *      2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
- *      3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
- *      2, 2, 2, 0, 3, 3, 3, 1, 1, 1 ;
+ *      11, 11, 11, 13, 13, 12, 12, 10, 13, 13,
+ *      12, 10, 10, 10, 11, 13, 13, 10, 10, 10,
+ *      13, 13, 10, 11, 11, 11, 12, 12, 13, 13,
+ *      12, 12, 12, 10, 13, 13, 13, 11, 11, 11 ;
  *
  *     var3 =
- *      0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
- *      1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
- *      2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
- *      1, 1, 1, 3, 2, 2, 2, 0, 0, 0 ;
+ *      10, 10, 10, 12, 12, 11, 11, 13, 12, 12,
+ *      11, 13, 13, 13, 10, 12, 12, 13, 13, 13,
+ *      12, 12, 13, 10, 10, 10, 11, 11, 12, 12,
+ *      11, 11, 11, 13, 12, 12, 12, 10, 10, 10 ;
  *    }
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -107,22 +107,22 @@ int check_contents_for_fail(int ncid, int *varid, int lineno)
 {
     /* all processes read entire variables back and check contents */
     int i, j, err, nprocs;
-    long long expected[4][NY*NX] = {{3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
-                                     0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
-                                     1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
-                                     0, 0, 0, 2, 1, 1, 1, 3, 3, 3},
-                                    {2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
-                                     3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
-                                     0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
-                                     3, 3, 3, 1, 0, 0, 0, 2, 2, 2},
-                                    {1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
-                                     2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
-                                     3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
-                                     2, 2, 2, 0, 3, 3, 3, 1, 1, 1},
-                                    {0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
-                                     1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
-                                     2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
-                                     1, 1, 1, 3, 2, 2, 2, 0, 0, 0}};
+    long long expected[4][NY*NX] = {{13, 13, 13, 11, 11, 10, 10, 12, 11, 11,
+                                     10, 12, 12, 12, 13, 11, 11, 12, 12, 12,
+                                     11, 11, 12, 13, 13, 13, 10, 10, 11, 11,
+                                     10, 10, 10, 12, 11, 11, 11, 13, 13, 13},
+                                    {12, 12, 12, 10, 10, 13, 13, 11, 10, 10,
+                                     13, 11, 11, 11, 12, 10, 10, 11, 11, 11,
+                                     10, 10, 11, 12, 12, 12, 13, 13, 10, 10,
+                                     13, 13, 13, 11, 10, 10, 10, 12, 12, 12},
+                                    {11, 11, 11, 13, 13, 12, 12, 10, 13, 13,
+                                     12, 10, 10, 10, 11, 13, 13, 10, 10, 10,
+                                     13, 13, 10, 11, 11, 11, 12, 12, 13, 13,
+                                     12, 12, 12, 10, 13, 13, 13, 11, 11, 11},
+                                    {10, 10, 10, 12, 12, 11, 11, 13, 12, 12,
+                                     11, 13, 13, 13, 10, 12, 12, 13, 13, 13,
+                                     12, 12, 13, 10, 10, 10, 11, 11, 12, 12,
+                                     11, 11, 11, 13, 12, 12, 12, 10, 10, 10}};
 
     long long *r_buffer = (long long*) malloc(NY*NX * sizeof(long long));
 
@@ -267,6 +267,9 @@ int main(int argc, char** argv)
         }
     }
 
+    for (i=0; i<4; i++)
+        buftype[i] = MPI_DATATYPE_NULL;
+
     /* only rank 0, 1, 2, and 3 do I/O:
      * each of ranks 0 to 3 write 4 nonblocking requests */
     nreqs = 4;
@@ -288,7 +291,7 @@ int main(int argc, char** argv)
 
         /* allocate I/O buffer and initialize its contents */
         buffer[i] = (long long*) malloc(req_lens[i] * sizeof(long long));
-        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank;
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank+10;
     }
     varname[0] = "var0";
     varname[1] = "var1";
@@ -332,6 +335,16 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%lld\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
     /* all processes read entire variables back and check contents */
     nerrs += check_contents_for_fail(ncid, varid, __LINE__);
 
@@ -342,7 +355,7 @@ int main(int argc, char** argv)
     cbuffer[0] = NULL;
     if (bufsize>0) cbuffer[0] = (long long*) malloc(bufsize * sizeof(long long));
     for (i=1; i<nreqs; i++) cbuffer[i] = cbuffer[i-1] + req_lens[i-1];
-    for (i=0; i<bufsize; i++) cbuffer[0][i] = rank;
+    for (i=0; i<bufsize; i++) cbuffer[0][i] = rank+10;
 
     /* create a new file for writing */
     cmode = NC_CLOBBER | NC_64BIT_DATA;
@@ -362,7 +375,6 @@ int main(int argc, char** argv)
                                        counts[i], cbuffer[i], &reqs[i]);
         ERR
     }
-
     err = ncmpi_enddef(ncid); ERR
 
     /* clear the file contents using a blocking API, before commit the
@@ -372,6 +384,16 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (cbuffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%lld\n", i,j,cbuffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
     /* all processes read entire variables back and check contents */
     nerrs += check_contents_for_fail(ncid, varid, __LINE__);
 
@@ -421,9 +443,18 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%lld\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
     /* all processes read entire variables back and check contents */
     nerrs += check_contents_for_fail(ncid, varid, __LINE__);
-
     /* commit read requests */
     nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
     err = ncmpi_wait_all(ncid, nreqs, reqs+4, sts);
@@ -433,9 +464,9 @@ int main(int argc, char** argv)
 
     for (i=0; i<nreqs; i++) {
         for (j=0; j<req_lens[i]; j++) {
-            if (cbuffer[i][j] != rank) {
+            if (cbuffer[i][j] != rank+10) {
                 printf("Error at line %d: expecting cbuffer[%d][%d]=%d but got %lld\n",
-                       __LINE__,i,j,rank,cbuffer[i][j]);
+                       __LINE__,i,j,rank+10,cbuffer[i][j]);
                 nerrs++;
             }
         }
@@ -448,7 +479,7 @@ int main(int argc, char** argv)
         MPI_Type_vector(req_lens[i], 1, 2, MPI_LONG_LONG, &buftype[i]);
         MPI_Type_commit(&buftype[i]);
         buffer[i] = (long long*) malloc(req_lens[i] * 2 * sizeof(long long));
-        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank+10;
         rbuffer[i] = (long long*) malloc(req_lens[i] * 2 * sizeof(long long));
         for (j=0; j<req_lens[i]*2; j++) rbuffer[i][j] = -1;
     }
@@ -471,7 +502,6 @@ int main(int argc, char** argv)
                               buffer[i], 1, buftype[i], &reqs[i]); ERR
         ERR
     }
-
     /* test flexible get API, using a noncontiguous buftype */
     for (i=0; i<nreqs; i++) {
         err = ncmpi_iget_varn(ncid, varid[i], my_nsegs[i], starts[i], counts[i],
@@ -481,7 +511,7 @@ int main(int argc, char** argv)
 
     for (i=0; i<nreqs; i++) MPI_Type_free(&buftype[i]);
 
-    /* read using a contiguous buffer. First swap back the starts[] and counts[].
+    /* read using a contiguous buffer. First swap back the starts[] and counts[]
      * swap segment 0 with segment 2 and swap segment 1 with segment 3
      */
     for (i=0; i<nreqs; i++) {
@@ -520,9 +550,9 @@ int main(int argc, char** argv)
                        __LINE__,i,j,rbuffer[i][j]);
                 nerrs++;
             }
-            if (j%2 == 0 && rbuffer[i][j] != rank) {
+            if (j%2 == 0 && rbuffer[i][j] != rank+10) {
                 printf("Error at line %d: expecting rbuffer[%d][%d]=%d but got %lld\n",
-                       __LINE__,i,j,rank,rbuffer[i][j]);
+                       __LINE__,i,j,rank+10,rbuffer[i][j]);
                 nerrs++;
             }
         }
@@ -535,9 +565,9 @@ int main(int argc, char** argv)
 
     for (i=0; i<nreqs; i++) {
         for (j=0; j<req_lens[i]; j++) {
-            if (cbuffer[i][j] != rank) {
+            if (cbuffer[i][j] != rank+10) {
                 printf("Error at line %d: expecting buffer[%d][%d]=%d but got %lld\n",
-                       __LINE__,i,j,rank,cbuffer[i][j]);
+                       __LINE__,i,j,rank+10,cbuffer[i][j]);
                 nerrs++;
             }
         }
@@ -548,6 +578,7 @@ int main(int argc, char** argv)
 
     if (bufsize>0) free(cbuffer[0]);
     for (i=0; i<nreqs; i++) free(buffer[i]);
+    for (i=0; i<nreqs; i++) free(rbuffer[i]);
     free(starts[0][0]);
     free(counts[0][0]);
     free(starts[0]);
diff --git a/test/nonblocking/i_varn_int64.c b/test/nonblocking/i_varn_int64.c
index 8dfa1a5..999bf2f 100644
--- a/test/nonblocking/i_varn_int64.c
+++ b/test/nonblocking/i_varn_int64.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: i_varn_int64.c 2219 2015-12-11 22:30:03Z wkliao $ */
+/* $Id: i_varn_int64.c 2400 2016-04-18 22:25:13Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example tests nonblocking varn APIs, including
@@ -32,28 +32,28 @@
  *    data:
  *
  *     var0 =
- *      3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
- *      0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
- *      1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
- *      0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *      13, 13, 13, 11, 11, 10, 10, 12, 11, 11,
+ *      10, 12, 12, 12, 13, 11, 11, 12, 12, 12,
+ *      11, 11, 12, 13, 13, 13, 10, 10, 11, 11,
+ *      10, 10, 10, 12, 11, 11, 11, 13, 13, 13 ;
  *
  *     var1 =
- *      2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
- *      3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
- *      0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
- *      3, 3, 3, 1, 0, 0, 0, 2, 2, 2 ;
+ *      12, 12, 12, 10, 10, 13, 13, 11, 10, 10,
+ *      13, 11, 11, 11, 12, 10, 10, 11, 11, 11,
+ *      10, 10, 11, 12, 12, 12, 13, 13, 10, 10,
+ *      13, 13, 13, 11, 10, 10, 10, 12, 12, 12 ;
  *
  *     var2 =
- *      1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
- *      2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
- *      3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
- *      2, 2, 2, 0, 3, 3, 3, 1, 1, 1 ;
+ *      11, 11, 11, 13, 13, 12, 12, 10, 13, 13,
+ *      12, 10, 10, 10, 11, 13, 13, 10, 10, 10,
+ *      13, 13, 10, 11, 11, 11, 12, 12, 13, 13,
+ *      12, 12, 12, 10, 13, 13, 13, 11, 11, 11 ;
  *
  *     var3 =
- *      0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
- *      1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
- *      2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
- *      1, 1, 1, 3, 2, 2, 2, 0, 0, 0 ;
+ *      10, 10, 10, 12, 12, 11, 11, 13, 12, 12,
+ *      11, 13, 13, 13, 10, 12, 12, 13, 13, 13,
+ *      12, 12, 13, 10, 10, 10, 11, 11, 12, 12,
+ *      11, 11, 11, 13, 12, 12, 12, 10, 10, 10 ;
  *    }
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -107,22 +107,22 @@ int check_contents_for_fail(int ncid, int *varid)
 {
     /* all processes read entire variables back and check contents */
     int i, j, err, nprocs;
-    long long expected[4][NY*NX] = {{3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
-                                     0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
-                                     1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
-                                     0, 0, 0, 2, 1, 1, 1, 3, 3, 3},
-                                    {2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
-                                     3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
-                                     0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
-                                     3, 3, 3, 1, 0, 0, 0, 2, 2, 2},
-                                    {1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
-                                     2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
-                                     3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
-                                     2, 2, 2, 0, 3, 3, 3, 1, 1, 1},
-                                    {0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
-                                     1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
-                                     2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
-                                     1, 1, 1, 3, 2, 2, 2, 0, 0, 0}};
+    long long expected[4][NY*NX] = {{13, 13, 13, 11, 11, 10, 10, 12, 11, 11,
+                                     10, 12, 12, 12, 13, 11, 11, 12, 12, 12,
+                                     11, 11, 12, 13, 13, 13, 10, 10, 11, 11,
+                                     10, 10, 10, 12, 11, 11, 11, 13, 13, 13},
+                                    {12, 12, 12, 10, 10, 13, 13, 11, 10, 10,
+                                     13, 11, 11, 11, 12, 10, 10, 11, 11, 11,
+                                     10, 10, 11, 12, 12, 12, 13, 13, 10, 10,
+                                     13, 13, 13, 11, 10, 10, 10, 12, 12, 12},
+                                    {11, 11, 11, 13, 13, 12, 12, 10, 13, 13,
+                                     12, 10, 10, 10, 11, 13, 13, 10, 10, 10,
+                                     13, 13, 10, 11, 11, 11, 12, 12, 13, 13,
+                                     12, 12, 12, 10, 13, 13, 13, 11, 11, 11},
+                                    {10, 10, 10, 12, 12, 11, 11, 13, 12, 12,
+                                     11, 13, 13, 13, 10, 12, 12, 13, 13, 13,
+                                     12, 12, 13, 10, 10, 10, 11, 11, 12, 12,
+                                     11, 11, 11, 13, 12, 12, 12, 10, 10, 10}};
 
     long long *r_buffer = (long long*) malloc(NY*NX * sizeof(long long));
 
@@ -307,7 +307,7 @@ int main(int argc, char** argv)
 
         /* allocate I/O buffer and initialize its contents */
         buffer[i] = (long long*) malloc(req_lens[i] * sizeof(long long));
-        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank;
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank+10;
     }
 
     /* write using varn API */
@@ -321,6 +321,16 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%lld\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
     /* all processes read entire variables back and check contents */
     nerrs += check_contents_for_fail(ncid, varid);
 
@@ -328,7 +338,7 @@ int main(int argc, char** argv)
     for (i=0; i<nreqs; i++) bufsize += req_lens[i];
     if (bufsize>0) cbuffer[0] = (long long*) malloc(bufsize * sizeof(long long));
     for (i=1; i<nreqs; i++) cbuffer[i] = cbuffer[i-1] + req_lens[i-1];
-    for (i=0; i<bufsize; i++) cbuffer[0][i] = rank;
+    for (i=0; i<bufsize; i++) cbuffer[0][i] = rank+10;
 
     /* write usning varn API */
     clear_file_contents(ncid, varid);
@@ -341,6 +351,16 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (cbuffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%lld\n", i,j,cbuffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
     /* all processes read entire variables back and check contents */
     nerrs += check_contents_for_fail(ncid, varid);
 
@@ -363,6 +383,16 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%lld\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
     /* all processes read entire variables back and check contents */
     nerrs += check_contents_for_fail(ncid, varid);
 
@@ -377,11 +407,12 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if read buffer contents are expected */
     for (i=0; i<nreqs; i++) {
         for (j=0; j<req_lens[i]; j++) {
-            if (buffer[i][j] != rank) {
+            if (buffer[i][j] != rank+10) {
                 printf("Error at line %d: expecting buffer[%d][%d]=%d but got %lld\n",
-                       __LINE__,i,j,rank,buffer[i][j]);
+                       __LINE__,i,j,rank+10,buffer[i][j]);
                 nerrs++;
             }
         }
@@ -396,7 +427,7 @@ int main(int argc, char** argv)
         MPI_Type_vector(req_lens[i], 1, 2, MPI_LONG_LONG, &buftype);
         MPI_Type_commit(&buftype);
         buffer[i] = (long long*) malloc(req_lens[i] * 2 * sizeof(long long));
-        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank+10;
 
         err = ncmpi_iput_varn(ncid, varid[i], my_nsegs[i], starts[i],
                               counts[i], buffer[i], 1, buftype, &reqs[i]);
@@ -407,6 +438,16 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]*2; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer altered buffer[%d][%d]=%lld\n", i,j,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
     /* all processes read entire variables back and check contents */
     nerrs += check_contents_for_fail(ncid, varid);
 
@@ -425,6 +466,7 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if read buffer contents are expected */
     for (i=0; i<nreqs; i++) {
         for (j=0; j<req_lens[i]*2; j++) {
             if (j%2 && buffer[i][j] != -1) {
@@ -432,9 +474,9 @@ int main(int argc, char** argv)
                        __LINE__,i,j,buffer[i][j]);
                 nerrs++;
             }
-            if (j%2 == 0 && buffer[i][j] != rank) {
+            if (j%2 == 0 && buffer[i][j] != rank+10) {
                 printf("Error at line %d: expecting buffer[%d][%d]=%d but got %lld\n",
-                       __LINE__,i,j,rank,buffer[i][j]);
+                       __LINE__,i,j,rank+10,buffer[i][j]);
                 nerrs++;
             }
         }
@@ -459,11 +501,12 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
     ERRS(nreqs, sts)
 
+    /* check if read buffer contents are expected */
     for (i=0; i<nreqs; i++) {
         for (j=0; j<req_lens[i]; j++) {
-            if (cbuffer[i][j] != rank) {
+            if (cbuffer[i][j] != rank+10) {
                 printf("Error at line %d: expecting buffer[%d][%d]=%d but got %lld\n",
-                       __LINE__,i,j,rank,cbuffer[i][j]);
+                       __LINE__,i,j,rank+10,cbuffer[i][j]);
                 nerrs++;
             }
         }
diff --git a/test/nonblocking/interleaved.c b/test/nonblocking/interleaved.c
index 23cc18d..1006054 100644
--- a/test/nonblocking/interleaved.c
+++ b/test/nonblocking/interleaved.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: interleaved.c 2133 2015-09-26 19:16:01Z wkliao $ */
+/* $Id: interleaved.c 2400 2016-04-18 22:25:13Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This program tests nonblocking APIs for handling interleaved file types.
@@ -55,6 +55,12 @@
 
 #define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__,ncmpi_strerror(err)); exit(-1);}
 
+#define CHECK_CONTENTS(exp) { \
+    if (buf[i] != (exp)) { \
+        printf("Error: put buffer[%d] altered to %d, expect %d\n",i,buf[i],(exp)); \
+        nerrs++; \
+    } \
+}
 int main(int argc, char** argv)
 {
     char filename[256];
@@ -144,6 +150,14 @@ int main(int argc, char** argv)
     err = ncmpi_wait_all(ncid, 3, req, st);
     ERR
 
+    /* check if write buffer contents have been altered */
+    for (i=0;  i<5;  i++) CHECK_CONTENTS(10 + i)
+    for (i=5;  i<10; i++) CHECK_CONTENTS(10 + i +  5)
+    for (i=10; i<15; i++) CHECK_CONTENTS(10 + i + 10)
+    for (i=15; i<20; i++) CHECK_CONTENTS(10 + i - 10)
+    for (i=20; i<25; i++) CHECK_CONTENTS(10 + i -  5)
+    for (i=25; i<30; i++) CHECK_CONTENTS(10 + i)
+
     err = ncmpi_close(ncid);
     ERR
 
diff --git a/test/nonblocking/mcoll_testf.f90 b/test/nonblocking/mcoll_testf.f90
index 4bde342..24dfa57 100644
--- a/test/nonblocking/mcoll_testf.f90
+++ b/test/nonblocking/mcoll_testf.f90
@@ -12,7 +12,7 @@
 ! 
 ! i=longitude, j=latitude, k=level
 !
-! $Id: mcoll_testf.f90 2131 2015-09-25 22:33:12Z wkliao $
+! $Id: mcoll_testf.f90 2512 2016-09-29 01:29:37Z wkliao $
 !
 !=============================================================================
 
@@ -180,8 +180,10 @@
 
       call MPI_Comm_Free (comm_cart, ierr)
 
-      msg = '*** TESTING F90 '//trim(cmd)//' for nf90mpi_iput_var API'
-      if (rank .EQ. 0) call pass_fail(0, msg)
+      if (rank .EQ. 0) then
+          msg='*** TESTING F90 '//trim(cmd)//' for nf90mpi_iput_var API'
+          call pass_fail(0, msg)
+      endif
 
  999  call MPI_Finalize(ierr)
 
diff --git a/test/nonblocking/mcoll_testf77.f b/test/nonblocking/mcoll_testf77.f
index c4cbe35..bda23af 100644
--- a/test/nonblocking/mcoll_testf77.f
+++ b/test/nonblocking/mcoll_testf77.f
@@ -13,7 +13,7 @@
 ! 
 ! i=longitude, j=latitude, k=level
 !
-! $Id: mcoll_testf77.f 2224 2015-12-16 06:10:36Z wkliao $
+! $Id: mcoll_testf77.f 2512 2016-09-29 01:29:37Z wkliao $
 !
 !=============================================================================
 
@@ -204,8 +204,10 @@
 
       call MPI_Comm_Free (comm_cart, ierr)
 
-      msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//' for iput API'
-      if (rank .EQ. 0) call pass_fail(0, msg)
+      if (rank .EQ. 0) then
+          msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//' for iput API'
+          call pass_fail(0, msg)
+      endif
 
  999  call MPI_Finalize  (ierr)
 
diff --git a/test/nonblocking/req_all.c b/test/nonblocking/req_all.c
index 6407792..4f9dfba 100644
--- a/test/nonblocking/req_all.c
+++ b/test/nonblocking/req_all.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id$ */
+/* $Id: req_all.c 2400 2016-04-18 22:25:13Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example shows how to use NC_REQ_ALL in nonblocking I/O operations.
@@ -32,24 +32,24 @@
  *    data:
  *    
  *     var_int =
- *      0, 0, 1, 1, 2, 2, 3, 3,
- *      0, 0, 1, 1, 2, 2, 3, 3,
- *      0, 0, 1, 1, 2, 2, 3, 3,
- *      0, 0, 1, 1, 2, 2, 3, 3,
- *      0, 0, 1, 1, 2, 2, 3, 3,
- *      0, 0, 1, 1, 2, 2, 3, 3,
- *      0, 0, 1, 1, 2, 2, 3, 3,
- *      0, 0, 1, 1, 2, 2, 3, 3 ;
+ *      10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13 ;
  *    
  *     var_flt =
- *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
- *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
- *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
- *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
- *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
- *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
- *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
- *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1 ;
+ *      10.5, 10.5, 11.5, 11.5, 12.5, 12.5, 13.5, 13.5,
+ *      10.5, 10.5, 11.5, 11.5, 12.5, 12.5, 13.5, 13.5,
+ *      10.5, 10.5, 11.5, 11.5, 12.5, 12.5, 13.5, 13.5,
+ *      10.5, 10.5, 11.5, 11.5, 12.5, 12.5, 13.5, 13.5,
+ *      10.5, 10.5, 11.5, 11.5, 12.5, 12.5, 13.5, 13.5,
+ *      10.5, 10.5, 11.5, 11.5, 12.5, 12.5, 13.5, 13.5,
+ *      10.5, 10.5, 11.5, 11.5, 12.5, 12.5, 13.5, 13.5,
+ *      10.5, 10.5, 11.5, 11.5, 12.5, 12.5, 13.5, 13.5 ;
  *    }
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -104,8 +104,8 @@ int main(int argc, char** argv)
 
     for (i=0; i<NY; i++)
         for (j=0; j<NX; j++) {
-             buf_int[i][j] = rank;
-             buf_flt[i][j] = 0.1 + rank;
+             buf_int[i][j] = rank+10;
+             buf_flt[i][j] = 10.5+rank;
         }
 
     /* define dimensions x and y */
@@ -132,6 +132,21 @@ int main(int argc, char** argv)
 
     err = ncmpi_wait_all(ncid, NC_REQ_ALL, NULL, NULL); ERR
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<NY; i++)
+        for (j=0; j<NX; j++) {
+             if (buf_int[i][j] != rank+10) {
+                 printf("Error at line %d: expecting buffer[%d][%d]=%d but got %d\n",
+                       __LINE__,i,j,rank+10,buf_int[i][j]);
+                 nerrs++;
+             }
+             if (buf_flt[i][j] != 10.5 + rank) {
+                 printf("Error at line %d: expecting buffer[%d][%d]=%f but got %f\n",
+                       __LINE__,i,j,10.5+rank,buf_flt[i][j]);
+                 nerrs++;
+             }
+        }
+
     err = ncmpi_close(ncid);
     ERR
 
diff --git a/test/nonblocking/test_bput.c b/test/nonblocking/test_bput.c
index 2660132..a90a793 100644
--- a/test/nonblocking/test_bput.c
+++ b/test/nonblocking/test_bput.c
@@ -1,9 +1,10 @@
-/*
- *  Copyright (C) 2012, Northwestern University
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: test_bput.c 2133 2015-09-26 19:16:01Z wkliao $
- */
+ *********************************************************************/
+/*  $Id: test_bput.c 2400 2016-04-18 22:25:13Z wkliao $ */
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -64,7 +65,7 @@ int main(int argc, char **argv) {
           62, 63, 64, 65, 66, 67,
           68, 69, 70, 71, 72, 73
      */
-    for (j=0; j<4; j++) for (i=0; i<6; i++) var[j][i] = j*6+i + 50;
+    for (j=0; j<4; j++) for (i=0; i<6; i++) var[j][i] = 50.5 + j*6+i;
 
     /* bufsize must be max of data type converted before and after */
     bufsize = 4*6*sizeof(long long);
@@ -82,10 +83,30 @@ int main(int argc, char **argv) {
     start[0]  = 0; start[1]  = 0;
     err = ncmpi_bput_varm_float(ncid, varid, start, count, stride, imap, &var[0][0], &req[0]); ERR
 
+    /* check if write buffer contents have been altered */
+    for (j=0; j<4; j++)
+        for (i=0; i<6; i++) {
+            if (var[j][i] != 50.5 + j*6+i) {
+                printf("Error: put buffer[%d][%d]=%f altered, should be %f\n",
+                       j,i,var[j][i],50.5+j*6+i);
+                nerrs++;
+            }
+        }
+
     /* write the second two columns of the NC variable in the matrix transposed way */
     start[0]  = 0; start[1]  = 2;
     err = ncmpi_bput_varm_float(ncid, varid, start, count, stride, imap, &var[2][0], &req[1]); ERR
 
+    /* check if write buffer contents have been altered */
+    for (j=0; j<4; j++)
+        for (i=0; i<6; i++) {
+            if (var[j][i] != 50.5 + j*6+i) {
+                printf("Error: put buffer[%d][%d]=%f altered, should be %f\n",
+                       j,i,var[j][i],50.5+j*6+i);
+                nerrs++;
+            }
+        }
+
     err = ncmpi_wait_all(ncid, 2, req, status); ERR
 
     /* check each bput status */
@@ -110,11 +131,10 @@ int main(int argc, char **argv) {
     /* check if the contents of write buffer have been altered (should not be) */
     for (j=0; j<4; j++) {
         for (i=0; i<6; i++) {
-            if (var[j][i] != j*6+i + 50) {
-#ifdef PRINT_ERR_ON_SCREEN
+            if (var[j][i] != 50.5+j*6+i) {
                 /* this error is a pntecdf internal error, if occurs */
-                printf("Error: bput_varm write buffer has been altered at j=%d i=%d\n",j,i);
-#endif
+                printf("Error: put buffer[%d][%d]=%f altered, should be %f\n",
+                       j,i,var[j][i],50.5+j*6+i);
                 nerrs++;
                 break;
             }
diff --git a/test/nonblocking/wait_after_indep.c b/test/nonblocking/wait_after_indep.c
index 206739d..0122977 100644
--- a/test/nonblocking/wait_after_indep.c
+++ b/test/nonblocking/wait_after_indep.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: wait_after_indep.c 2133 2015-09-26 19:16:01Z wkliao $ */
+/* $Id: wait_after_indep.c 2400 2016-04-18 22:25:13Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *
@@ -57,7 +57,7 @@ int main(int argc, char** argv)
     err = ncmpi_def_var(ncid, "var", NC_UBYTE, NDIMS, dimid, &varid); ERR
     err = ncmpi_enddef(ncid); ERR
 
-    for (i=0; i<NY; i++) for (j=0; j<NX; j++) buffer[i][j] = rank;
+    for (i=0; i<NY; i++) for (j=0; j<NX; j++) buffer[i][j] = rank+10;
 
      start[0] = 0;     start[1] = NX*rank;
      count[0] = NY/2;  count[1] = NX/2;
@@ -68,11 +68,32 @@ int main(int argc, char** argv)
     err = ncmpi_bput_vars_uchar(ncid, varid, start, count, stride,
                                 &buffer[0][0], &req);
     ERR
+
+    /* check if write buffer contents have been altered */
+    for (i=0; i<NY; i++)
+        for (j=0; j<NX; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer[%d][%d]=%hhu altered, should be %d\n",
+                       i,j,buffer[i][j],rank+10);
+                nerrs++;
+            }
+        }
+
     err = ncmpi_end_indep_data(ncid); ERR
 
     /* calling wait API after exiting independent data mode on purpose */
     err = ncmpi_wait_all(ncid, 1, &req, &st); ERR
 
+    /* check if write buffer contents have been altered */
+    for (i=0; i<NY; i++)
+        for (j=0; j<NX; j++) {
+            if (buffer[i][j] != rank+10) {
+                printf("Error: put buffer[%d][%d]=%hhu altered, should be %d\n",
+                       i,j,buffer[i][j],rank+10);
+                nerrs++;
+            }
+        }
+
     err = ncmpi_buffer_detach(ncid); ERR
     err = ncmpi_close(ncid); ERR
 
diff --git a/test/subfile/Makefile.in b/test/subfile/Makefile.in
index e235239..e1de7a0 100644
--- a/test/subfile/Makefile.in
+++ b/test/subfile/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2013, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+# $Id: Makefile.in 2590 2016-10-31 21:37:02Z wkliao $
 #
 # @configure_input@
 
@@ -16,9 +16,6 @@ FPPFLAGS += -I../../src/libf @FC_MODINC at ../../src/libf90
 F90FLAGS += @FC_MODOUT at .
 LDFLAGS  := $(LDFLAGS) -L../common
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
-ifeq (@PNC_DEBUG@, yes)
-CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
-endif
 
 C_SRCS   = test_subfile.c
 
diff --git a/test/testcases/Makefile.in b/test/testcases/Makefile.in
index db72a97..52cc021 100644
--- a/test/testcases/Makefile.in
+++ b/test/testcases/Makefile.in
@@ -2,7 +2,7 @@
 # Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 # See COPYRIGHT notice in top-level directory.
 #
-# $Id: Makefile.in 2318 2016-02-04 00:18:26Z wkliao $
+# $Id: Makefile.in 2614 2016-11-12 19:50:02Z wkliao $
 #
 # @configure_input@
 
@@ -14,17 +14,16 @@ include ../../macros.make
 INCLUDES  = -I../../src/lib -I$(srcdir)/../common
 FPPFLAGS += -I../../src/libf @FC_MODINC at ../../src/libf90
 ifeq (@SIZEOF_MPI_AINT_IS_4@, yes)
-FPPFLAGS += -DSIZEOF_MPI_AINT_IS_4
+FPPFLAGS += $(FC_DEFINE)SIZEOF_MPI_AINT_IS_4
 endif
 LDFLAGS  := $(LDFLAGS) -L../common
 LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
-ifeq (@PNC_DEBUG@, yes)
-CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
-endif
 
 NCMPIGEN  = ../../src/utils/ncmpigen/ncmpigen
 NCMPIDIFF = ../../src/utils/ncmpidiff/ncmpidiff
 
+M4_SRCS  = erange_fill.m4
+
 C_SRCS   = ncmpi_vars_null_stride.c \
            vectors.c \
            collective_error.c \
@@ -50,6 +49,7 @@ C_SRCS   = ncmpi_vars_null_stride.c \
            last_large_var.c \
            check_type.c \
            test_erange.c \
+           scalar.c \
            redef1.c
 
 F77_SRCS = varn_intf.f \
@@ -65,7 +65,7 @@ F90_SRCS = inq_num_varsf.f90 \
            varn_real.f90
 
 PROGS    = $(C_SRCS:.c=)
-OBJS     = $(C_SRCS:.c=.o)
+OBJS     = $(C_SRCS:.c=.o) $(M4_SRCS:.m4=.o)
 
 ifeq (@has_fortran@, yes)
 PROGS   += $(F77_SRCS:.f=)   $(F77F_SRCS:.F=)
@@ -80,8 +80,12 @@ OBJS    += bigrecords.o
 endif
 endif
 
-GARBAGE      = $(PROGS) *.nc
-PACKING_LIST = $(C_SRCS) $(F77_SRCS) $(F77F_SRCS) $(F90_SRCS) \
+ifeq (@enable_erange_fill@, yes)
+PROGS   += $(M4_SRCS:.m4=)
+endif
+
+GARBAGE      = $(PROGS) *.nc $(M4_SRCS:.m4=.c)
+PACKING_LIST = $(C_SRCS) $(M4_SRCS) $(F77_SRCS) $(F77F_SRCS) $(F90_SRCS) \
                bigrecords.f \
                Makefile.in depend \
                geopotential.ncdump \
@@ -182,6 +186,12 @@ check_type: check_type.o $(LIBRARY)
 test_erange: test_erange.o $(LIBRARY)
 	$(LINK.c) $< $(LDFLAGS) $(LIBS)
 
+scalar: scalar.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+erange_fill: erange_fill.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
 inq_num_varsf: inq_num_varsf.o $(LIBRARY)
 	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
 
diff --git a/test/testcases/add_var.c b/test/testcases/add_var.c
index 725f29d..c2b8a3f 100644
--- a/test/testcases/add_var.c
+++ b/test/testcases/add_var.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: add_var.c 2169 2015-11-10 22:44:11Z wkliao $
+ *  $Id: add_var.c 2367 2016-03-22 03:54:38Z wkliao $
  */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -74,7 +74,7 @@ int main(int argc, char** argv) {
     err = ncmpi_def_dim(ncid, "new_dim_1", 5, &dimid[0]); ERR
     err = ncmpi_def_dim(ncid, "new_dim_2", 4, &dimid[1]); ERR
 
-    /* add 2 new dimensions */
+    /* add 2 new variables */
     err = ncmpi_def_var(ncid, "new_var1", NC_INT,   2, dimid, &varid); ERR
     err = ncmpi_def_var(ncid, "new_var2", NC_FLOAT, 2, dimid, &varid); ERR
     err = ncmpi_enddef(ncid); ERR
diff --git a/test/testcases/alignment_test.c b/test/testcases/alignment_test.c
index 862ce02..904bd5c 100644
--- a/test/testcases/alignment_test.c
+++ b/test/testcases/alignment_test.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: alignment_test.c 2133 2015-09-26 19:16:01Z wkliao $
+ *  $Id: alignment_test.c 2399 2016-04-17 18:59:32Z wkliao $
  */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -97,6 +97,14 @@ int main(int argc, char** argv) {
             start[0] = NX*rank;
             count[0] = NX;
             err = ncmpi_put_vara_int_all(ncid, varid[i], start, count, buf); ERR
+            /* check if user put buffer contents altered */
+            for (j=0; j<NX; j++) {
+                if (buf[j] != rank*1000 + i*10 + j) {
+                    printf("Error: user put buffer[%d] altered from %d to %d\n",
+                           j, rank*1000 + i*10 + j, buf[j]);
+                    nerrs++;
+                }
+            }
         }
 #endif
 #ifdef TEST_RECORD_VAR
@@ -107,6 +115,14 @@ int main(int argc, char** argv) {
             for (j=0; j<NX; j++) buf[j] = rank*1000 + 100 + i*10 + j;
             start[0] = 1; /* write 2nd record */
             err = ncmpi_put_vara_int_all(ncid, varid[i], start, count, buf); ERR
+            /* check if user put buffer contents altered */
+            for (j=0; j<NX; j++) {
+                if (buf[j] != rank*1000 + 100 + i*10 + j) {
+                    printf("Error: user put buffer[%d] altered from %d to %d\n",
+                           j, rank*1000 + 100 + i*10 + j, buf[j]);
+                    nerrs++;
+                }
+            }
         }
 #endif
     }
@@ -221,6 +237,14 @@ int main(int argc, char** argv) {
             start[0] = NX*rank;
             count[0] = NX;
             err = ncmpi_put_vara_int_all(ncid, new_varid[i], start, count, buf); ERR
+            /* check if user put buffer contents altered */
+            for (j=0; j<NX; j++) {
+                if (buf[j] != -1 * (i*10 + j)) {
+                    printf("Error: user put buffer[%d] altered from %d to %d\n",
+                           j, -1 * (i*10 + j), buf[j]);
+                    nerrs++;
+                }
+            }
         }
 #endif
 #ifdef TEST_RECORD_VAR
@@ -231,6 +255,14 @@ int main(int argc, char** argv) {
             for (j=0; j<NX; j++) buf[j] = -1 * (100 + i*10 + j);
             start[0] = 1; /* write 2nd record */
             err = ncmpi_put_vara_int_all(ncid, new_varid[i], start, count, buf); ERR
+            /* check if user put buffer contents altered */
+            for (j=0; j<NX; j++) {
+                if (buf[j] != -1 * (100 + i*10 + j)) {
+                    printf("Error: user put buffer[%d] altered from %d to %d\n",
+                           j, -1 * (100 + i*10 + j), buf[j]);
+                    nerrs++;
+                }
+            }
         }
 #endif
     }
diff --git a/test/testcases/attrf.f b/test/testcases/attrf.f
index cf3eddf..9fec783 100644
--- a/test/testcases/attrf.f
+++ b/test/testcases/attrf.f
@@ -2,7 +2,7 @@
 !   Copyright (C) 2015, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: attrf.f 2263 2015-12-22 15:42:05Z wkliao $
+! $Id: attrf.f 2512 2016-09-29 01:29:37Z wkliao $
 
 ! This program tests if NF_ERANGE is properly returned with a coredump
 ! when an out-of-range value is used to write to a global attribute.
@@ -45,9 +45,9 @@
           include "mpif.h"
           include "pnetcdf.inc"
 
-          real                    buf_flt
+          real                    buf_flt, one_flt
           double precision        buf_dbl
-          integer                 buf_int, XTRIM
+          integer                 buf_int, XTRIM, cmode
           integer*2 buf_int2
           integer*8 buf_int8, one
 
@@ -60,6 +60,8 @@
           call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
 
           one = 1
+          one_flt = 1.0
+
           ! take filename from command-line argument if there is any
           if (rank .EQ. 0) then
               filename = "testfile.nc"
@@ -73,7 +75,8 @@
 
           nerrs = 0
 
-          err = nfmpi_create(MPI_COMM_WORLD, filename, NF_CLOBBER,
+          cmode = IOR(NF_CLOBBER,NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
      +                       MPI_INFO_NULL, ncid)
           call check(err, 'In nfmpi_create: ', nerrs)
 
@@ -91,6 +94,9 @@
               nerrs = nerrs + 1
               ! Note: even with an error, the attribute is still being created
           endif
+          err = nfmpi_put_att_real(ncid, NF_GLOBAL, "attr1", NF_INT,
+     +                             one, one_flt)
+          call check(err, 'In nfmpi_put_att_real: ', nerrs)
 
           err = nfmpi_put_att_double(ncid, NF_GLOBAL, "attr2", NF_INT,
      +                               one, buf_dbl)
@@ -99,7 +105,12 @@
               if (err .NE. NF_NOERR) print*, nfmpi_strerror(err)
               nerrs = nerrs + 1
               ! Note: even with an error, the attribute is still being created
+              ! in this case, valgrind complains about uninitialised buffer at
+              ! nfmpi_enddef when writing header to file.
           endif
+          err = nfmpi_put_att_real(ncid, NF_GLOBAL, "attr2", NF_INT,
+     +                             one, one_flt)
+          call check(err, 'In nfmpi_put_att_real: ', nerrs)
 
           err = nfmpi_put_att_int8(ncid, NF_GLOBAL, "attr3", NF_INT,
      +                             one, buf_int8)
@@ -108,18 +119,28 @@
               if (err .NE. NF_NOERR) print*, nfmpi_strerror(err)
               nerrs = nerrs + 1
               ! Note: even with an error, the attribute is still being created
+              ! in this case, valgrind complains about uninitialised buffer at
+              ! nfmpi_enddef when writing header to file.
           endif
+          err = nfmpi_put_att_int8(ncid, NF_GLOBAL, "attr3", NF_INT,
+     +                             one, one)
+          call check(err, 'In nfmpi_put_att_int8: ', nerrs)
 
           buf_int = 2147483647
           err = nfmpi_put_att_int(ncid, NF_GLOBAL, "attr4", NF_INT,
      +                            one, buf_int)
           call check(err, 'In nfmpi_put_att_int: ', nerrs)
 
-          ! because of the NF_ERANGE error, the attributes may become
+          ! Because of the NF_ERANGE error, the attributes may become
           ! inconsistent among processes, So NC_EMULTIDEFINE_ATTR_VAL
-          ! or NF_EMULTIDEFINE may be returned from nfmpi_enddef.
+          ! or NF_EMULTIDEFINE may be returned from nfmpi_enddef (1.7.0
+          ! and before), or nfmpi_put_att_xxx (after 1.7.0 when in safe
+          ! mode).
           ! While in safe mode, the warning message of inconsistent metadata
           ! may appear on the screen. This is expected.
+          ! In addition, when running under valgrind, NF_ERANGE can
+          ! cause skipping requests and a valgrind warning message of
+          ! "uninitialised byte", which is also expected.
           err = nfmpi_enddef(ncid)
           if (err .NE. NF_NOERR .AND. err .NE. NF_EMULTIDEFINE .AND.
      +        err .NE. NF_EMULTIDEFINE_ATTR_VAL)
@@ -132,6 +153,22 @@
               nerrs = nerrs + 1
           endif
 
+          ! check if can overwrite an attribute in data mode
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "attr4", NF_INT,
+     +                            one, buf_int)
+          call check(err, 'In nfmpi_put_att_int: ', nerrs)
+
+          buf_int2 = 32767
+          err = nfmpi_put_att_int2(ncid, NF_GLOBAL, "attr4", NF_INT2,
+     +                             one, buf_int2)
+          call check(err, 'In nfmpi_put_att_int: xxxxxxx', nerrs)
+
+          err = nfmpi_put_att_int8(ncid, NF_GLOBAL, "attr4", NF_INT64,
+     +                             one, buf_int8)
+          if (err .NE. NF_ENOTINDEFINE)
+     +       print*,'Error: expect error code NF_ENOTINDEFINE but got ',
+     +       err
+
           err = nfmpi_close(ncid)
           call check(err, 'In nfmpi_close: ', nerrs)
 
@@ -139,7 +176,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8,
      +                        MPI_SUM, 0, MPI_COMM_WORLD, ierr)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
@@ -147,9 +184,11 @@
      +            sum_size/1048576, ' MiB yet to be freed'
           endif
 
-          msg ='*** TESTING F77 '//cmd(1:XTRIM(cmd))//
-     +         ' for attribute overflow '
-          if (rank .eq. 0) call pass_fail(nerrs, msg)
+          if (rank .eq. 0) then
+              msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
+     +              ' for attribute overflow '
+              call pass_fail(nerrs, msg)
+          endif
 
  999      call MPI_Finalize(ierr)
 
diff --git a/test/testcases/buftype_free.c b/test/testcases/buftype_free.c
index aa0234f..e21cfc4 100644
--- a/test/testcases/buftype_free.c
+++ b/test/testcases/buftype_free.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: buftype_free.c 2165 2015-11-05 07:18:49Z wkliao $
+ *  $Id: buftype_free.c 2399 2016-04-17 18:59:32Z wkliao $
  */
 
 /*
@@ -64,7 +64,7 @@ int main(int argc, char **argv) {
     err = ncmpi_enddef(ncid); ERR
 
     /* initialize the contents of the array */
-    for (i=0; i<4; i++) for (j=0; j<(NY+4)*(NX+4); j++) buf[i][j] = rank;
+    for (i=0; i<4; i++) for (j=0; j<(NY+4)*(NX+4); j++) buf[i][j] = rank+10;
 
     start[0] = NY*rank; start[1] = 0;
     count[0] = NY;      count[1] = NX;
@@ -74,6 +74,16 @@ int main(int argc, char **argv) {
     err = ncmpi_put_vara_int_all(ncid, varid[2], start, count, buf[2]); ERR
     err = ncmpi_put_vara_int_all(ncid, varid[3], start, count, buf[3]); ERR
 
+    /* check if user write buffer contents altered */
+    for (i=0; i<4; i++) {
+        for (j=0; j<(NY+4)*(NX+4); j++) {
+            if (buf[i][j] != rank+10) {
+                printf("Error: user put buffer[%d][%d] altered from %d to %d\n",
+                       i,j, rank+10, buf[i][j]);
+                nerrs++;
+            }
+        }
+    }
 
     /* define an MPI datatype using MPI_Type_create_subarray() */
     ghost      = 2;
diff --git a/test/testcases/buftype_freef.f b/test/testcases/buftype_freef.f
index e3dfcf1..40a587a 100644
--- a/test/testcases/buftype_freef.f
+++ b/test/testcases/buftype_freef.f
@@ -2,7 +2,7 @@
 !   Copyright (C) 2015, Northwestern University
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: buftype_freef.f 2224 2015-12-16 06:10:36Z wkliao $
+! $Id: buftype_freef.f 2512 2016-09-29 01:29:37Z wkliao $
 
 ! This example tests if PnetCDF duplicates the MPI derived data type supplied
 ! by the user, when calling the flexible APIs. It tests a PnetCDF bug
@@ -51,9 +51,9 @@
           PARAMETER(NREQS=4, NX=4, NY=4)
 
           character*256 filename, cmd, msg, varname, str
-          integer i, err, ierr, nprocs, rank, nerrs, get_args
+          integer i, j, err, ierr, nprocs, rank, nerrs, get_args
           integer ncid, ghost
-          integer var(64,4), varid(4), dimid(2), req(4), st(4)
+          integer buf(64,4), varid(4), dimid(2), req(4), st(4)
           integer buftype(4), gsize(2), subsize(2), a_start(2)
           integer*8 start(2), count(2)
           integer*8 one, malloc_size, sum_size
@@ -75,6 +75,13 @@
 
           nerrs = 0
 
+          ! initialize I/O buffer
+          do j=1,4
+             do i=1,64
+                buf(i,j) = rank
+             enddo
+          enddo
+
           ! create file, truncate it if exists
           err = nfmpi_create(MPI_COMM_WORLD, filename, NF_CLOBBER,
      +                        MPI_INFO_NULL, ncid)
@@ -107,7 +114,7 @@
 
           do i=1, NREQS
              err = nfmpi_put_vara_int_all(ncid, varid(i), start, count,
-     +                                    var(1,i))
+     +                                    buf(1,i))
              call check(err, 'In nfmpi_put_vara_int_all: ')
           enddo
 
@@ -127,7 +134,7 @@
               call MPI_Type_commit(buftype(i), err)
 
               err = nfmpi_iget_vara(ncid, varid(i), start, count,
-     +                              var(1,i), one, buftype(i), req(i))
+     +                              buf(1,i), one, buftype(i), req(i))
               call check(err, 'In nfmpi_iget_vara ')
               ! immediately free the data type
               call MPI_Type_free(buftype(i), err)
@@ -152,7 +159,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8,
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
@@ -160,9 +167,11 @@
      +            sum_size/1048576, ' MiB yet to be freed'
           endif
 
-          msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
-     +          ' for flexible API '
-          if (rank .eq. 0) call pass_fail(nerrs, msg)
+          if (rank .eq. 0) then
+              msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
+     +              ' for flexible API '
+              call pass_fail(nerrs, msg)
+          endif
 
  999      call MPI_Finalize(ierr)
       end ! program main
diff --git a/test/testcases/check_type.c b/test/testcases/check_type.c
index b519ce9..b54bcb1 100644
--- a/test/testcases/check_type.c
+++ b/test/testcases/check_type.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id$
+ *  $Id: check_type.c 2567 2016-10-20 23:18:58Z wkliao $
  */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
diff --git a/test/testcases/collective_error.c b/test/testcases/collective_error.c
index 571176d..337f109 100644
--- a/test/testcases/collective_error.c
+++ b/test/testcases/collective_error.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: collective_error.c 2133 2015-09-26 19:16:01Z wkliao $
+ *  $Id: collective_error.c 2614 2016-11-12 19:50:02Z wkliao $
  */
 
 /* This test program checks if a collective API can be nicely aborted without
@@ -23,7 +23,7 @@
    if (rank == 0 && err != NC_NOERR) \
        printf("PE %d: %s error is %s\n",rank,fn,ncmpi_strerror(err)); \
    if (rank == 1 && err != NC_EINVALCOORDS) \
-       printf("PE %d: %s error code should be NC_EINVALCOORDS but got %s",rank,fn,nc_err_code_name(err)); \
+       printf("PE %d: %s error code should be NC_EINVALCOORDS but got %s\n",rank,fn,nc_err_code_name(err)); \
 }
 
 int main(int argc, char *argv[])
@@ -72,25 +72,70 @@ int main(int argc, char *argv[])
         start[0] = 0;
         count[0] = 2;
     } else if (rank == 1) {
-        start[0] = 2; /* illegal for a start > defined shape */
+#if defined(PNETCDF_RELAX_COORD_BOUND) && PNETCDF_RELAX_COORD_BOUND==1
+        start[0] = 3; /* illegal for a start > defined shape */
+#else
+        start[0] = 2; /* illegal for a start >= defined shape */
+#endif
         count[0] = 0;
     }
-    else
+    else {
+        start[0] = 0;
         count[0] = 0;
+    }
+
+    buf[0] = 1.0;
+    buf[1] = 2.0;
 
     err = ncmpi_put_vara_all(ncid, varid, start, count,
 			     buf, count[0], MPI_DOUBLE);
     CHECK_ERROR("ncmpi_put_vara_all")
 
+    /* check if user put buffer contents altered */
+    if (buf[0] != 1.0) {
+        printf("Error: user put buffer[%d] altered from %f to %f\n",
+               0, 1.0, buf[0]);
+        nerrs++;
+    }
+    if (buf[1] != 2.0) {
+        printf("Error: user put buffer[%d] altered from %f to %f\n",
+               1, 2.0, buf[1]);
+        nerrs++;
+    }
+
     err = ncmpi_put_vara_double_all(ncid, varid, start, count, buf);
     CHECK_ERROR("ncmpi_put_vara_double_all")
 
+    /* check if user put buffer contents altered */
+    if (buf[0] != 1.0) {
+        printf("Error: user put buffer[%d] altered from %f to %f\n",
+               0, 1.0, buf[0]);
+        nerrs++;
+    }
+    if (buf[1] != 2.0) {
+        printf("Error: user put buffer[%d] altered from %f to %f\n",
+               1, 2.0, buf[1]);
+        nerrs++;
+    }
+
     err = ncmpi_iput_vara_double(ncid, varid, start, count, buf, &req);
     CHECK_ERROR("ncmpi_iput_vara_double")
 
     err = ncmpi_wait_all(ncid, 1, &req, &status);
     ERR
 
+    /* check if user put buffer contents altered */
+    if (buf[0] != 1.0) {
+        printf("Error: user put buffer[%d] altered from %f to %f\n",
+               0, 1.0, buf[0]);
+        nerrs++;
+    }
+    if (buf[1] != 2.0) {
+        printf("Error: user put buffer[%d] altered from %f to %f\n",
+               1, 2.0, buf[1]);
+        nerrs++;
+    }
+
     err = ncmpi_get_vara_all(ncid, varid, start, count,
 			     buf, count[0], MPI_DOUBLE);
     CHECK_ERROR("ncmpi_get_vara_all")
diff --git a/test/testcases/depend b/test/testcases/depend
index 3989a50..6eafbf2 100644
--- a/test/testcases/depend
+++ b/test/testcases/depend
@@ -35,3 +35,5 @@ put_parameter.o: put_parameter.f
 last_large_var.o: last_large_var.c
 check_type.o: check_type.c
 test_erange.o: test_erange.c
+scalar.o: scalar.c
+erange_fill.o: erange_fill.c
diff --git a/test/testcases/erange_fill.m4 b/test/testcases/erange_fill.m4
new file mode 100644
index 0000000..ea89e78
--- /dev/null
+++ b/test/testcases/erange_fill.m4
@@ -0,0 +1,409 @@
+/*
+ *  Copyright (C) 2016, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: erange_fill.m4 2577 2016-10-25 00:03:31Z wkliao $
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program is only active when macro ERANGE_FILL is defined.
+ * It tests whether the data elemensts is "filled" with "filled values" when
+ * their contents (to be read or written) cause NC_ERANGE error.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -g -o erange_fill.c erange_fill -lpnetcdf
+ *
+ *    % mpiexec -l -n 1 erange_fill erange_fill.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define LEN 10
+
+#define ERR {if(err!=NC_NOERR){printf("Error at %s line %d: %s\n",__func__,__LINE__, ncmpi_strerror(err)); nerrs++;}}
+
+#define ERR_EXPECT(expect) { \
+    if (err != expect) { \
+        printf("Error at %s line %d: expect %s but got %s\n", \
+               __func__,__LINE__,nc_err_code_name(NC_ERANGE),nc_err_code_name(err)); \
+        nerrs++; \
+    } \
+}
+
+include(`foreach.m4')dnl
+include(`utils.m4')dnl
+
+#define text char
+
+#ifndef schar
+#define schar signed char
+#endif
+#ifndef uchar
+#define uchar unsigned char
+#endif
+#ifndef ushort
+#define ushort unsigned short
+#endif
+#ifndef uint
+#define uint unsigned int
+#endif
+#ifndef longlong
+#define longlong long long
+#endif
+#ifndef ulonglong
+#define ulonglong unsigned long long
+#endif
+
+define(`ITYPE_SIZE',`ifelse(
+`$1', `text',      `1',dnl
+`$1', `schar',     `1',dnl
+`$1', `uchar',     `1',dnl
+`$1', `short',     `2',dnl
+`$1', `ushort',    `2',dnl
+`$1', `int',       `4',dnl
+`$1', `long',      `4',dnl
+`$1', `uint',      `4',dnl
+`$1', `float',     `4',dnl
+`$1', `double',    `8',dnl
+`$1', `longlong',  `8',dnl
+`$1', `ulonglong', `8')')dnl
+
+static
+int test_default_fill_mode(char* filename) {
+    int err, nerrs=0, ncid, old_mode;
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    /* create a new file */
+    err = ncmpi_create(comm, filename, NC_CLOBBER, info, &ncid); ERR
+    err = ncmpi_set_fill(ncid, NC_FILL, &old_mode); ERR
+    if (old_mode == NC_FILL) {
+        printf("Error at %s line %d: expected NC_NOFILL but got NC_FILL\n",__func__,__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+    return nerrs;
+}
+
+define(`TEST_DEFAULT_FILL',dnl
+`dnl
+static
+int test_default_fill_$1(char* filename) {
+    int i, err, nerrs=0, ncid, dimid, omode, varid;
+    $1 buf[LEN];
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    /* create a new file */
+    err = ncmpi_create(comm, filename, NC_CLOBBER, info, &ncid); ERR
+    err = ncmpi_set_fill(ncid, NC_FILL, NULL); ERR
+    err = ncmpi_def_dim(ncid, "X", LEN, &dimid); ERR
+    err = ncmpi_def_var(ncid, "var", NC_TYPE($1), 1, &dimid, &varid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    /* reopen the file and check the contents of variable */
+    omode = NC_NOWRITE;
+    err = ncmpi_open(comm, filename, omode, info, &ncid); ERR
+    err = ncmpi_inq_varid(ncid, "var", &varid); ERR
+    err = GET_VAR($1)(ncid, varid, buf); ERR
+    for (i=0; i<LEN; i++) {
+        if (buf[i] != NC_FILL_VALUE($1)) {
+            printf("Error at %s line %d: expect buf[%d]=IFMT($1) but got IFMT($1)\n",
+                   __func__,__LINE__,i,($1)NC_FILL_VALUE($1),buf[i]);
+            nerrs++;
+        }
+    }
+    err = ncmpi_close(ncid); ERR
+    return nerrs;
+}
+')dnl
+
+foreach(`itype', (ITYPE_LIST), `TEST_DEFAULT_FILL(itype)')
+
+define(`TEST_USER_FILL',dnl
+`dnl
+static
+int test_user_fill_$1(char* filename, $1 fillv) {
+    int i, err, nerrs=0, ncid, dimid, omode, varid;
+    $1 buf[LEN];
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    /* create a new file */
+    err = ncmpi_create(comm, filename, NC_CLOBBER, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "X", LEN, &dimid); ERR
+    err = ncmpi_def_var(ncid, "var", NC_TYPE($1), 1, &dimid, &varid); ERR
+    err = ncmpi_put_att(ncid, varid, "_FillValue", NC_TYPE($1), 1, &fillv); ERR
+    err = ncmpi_close(ncid); ERR
+
+    /* reopen the file and check the contents of variable */
+    omode = NC_NOWRITE;
+    err = ncmpi_open(comm, filename, omode, info, &ncid); ERR
+    err = ncmpi_inq_varid(ncid, "var", &varid); ERR
+    err = GET_VAR($1)(ncid, varid, buf); ERR
+    for (i=0; i<LEN; i++) {
+        if (memcmp(&buf[i], &fillv, ITYPE_SIZE($1))) {
+            printf("Error at %s line %d: expect buf[%d]=IFMT($1) but got IFMT($1)\n",
+                   __func__,__LINE__,i,($1)fillv,buf[i]);
+            nerrs++;
+        }
+    }
+    err = ncmpi_close(ncid); ERR
+    return nerrs;
+}
+')dnl
+
+foreach(`itype', (ITYPE_LIST), `TEST_USER_FILL(itype)')
+
+define(`TEST_ERANGE_PUT',dnl
+`dnl
+static
+int test_erange_put_$1_$2(char* filename) {
+    int i, err, nerrs=0, ncid, dimid, omode, varid, cdf;
+    $1 buf[LEN];
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    /* create a new file */
+    err = ncmpi_create(comm, filename, NC_CLOBBER, info, &ncid); ERR
+    err = ncmpi_set_fill(ncid, NC_FILL, NULL); ERR
+    err = ncmpi_def_dim(ncid, "X", LEN, &dimid); ERR
+    err = ncmpi_def_var(ncid, "var", NC_TYPE($1), 1, &dimid, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    err = ncmpi_inq_format(ncid, &cdf); ERR
+
+    /* put data with ERANGE values */
+    $2 wbuf[LEN];
+    for (i=0; i<LEN; i++) wbuf[i] = ($2) ifelse(index(`$1',`u'), 0, `-1', `XTYPE_MAX($2)');
+    err = PUT_VAR($2)(ncid, varid, wbuf);
+    ifelse(`$1',`schar',`ifelse(`$2',`uchar',`if (cdf == NC_FORMAT_CDF2) ERR',`ERR_EXPECT(NC_ERANGE)')',`ERR_EXPECT(NC_ERANGE)')
+
+    err = ncmpi_close(ncid); ERR
+
+    /* reopen the file and check the contents of variable */
+    omode = NC_NOWRITE;
+    err = ncmpi_open(comm, filename, omode, info, &ncid); ERR
+    err = ncmpi_inq_varid(ncid, "var", &varid); ERR
+    err = GET_VAR($1)(ncid, varid, buf); ERR
+    for (i=0; i<LEN; i++) {
+        $1 expect = ($1)NC_FILL_VALUE($1);
+        ifelse(`$1',`schar',`ifelse(`$2',`uchar',`if (cdf != NC_FORMAT_CDF5) expect = ($1)wbuf[i];')')
+        if (buf[i] != expect) {
+            printf("Error at %s line %d: expect buf[%d]=IFMT($1) but got IFMT($1)\n",
+                   __func__,__LINE__,i,expect,buf[i]);
+            nerrs++;
+        }
+    }
+    err = ncmpi_close(ncid); ERR
+    return nerrs;
+}
+')dnl
+
+foreach(`itype',(uchar,short,ushort,int,uint,float,double,longlong,ulonglong),`TEST_ERANGE_PUT(schar, itype)')
+foreach(`itype',(schar,short,ushort,int,uint,float,double,longlong,ulonglong),`TEST_ERANGE_PUT(uchar, itype)')
+foreach(`itype',(ushort,int,uint,float,double,longlong,ulonglong),`TEST_ERANGE_PUT(short, itype)')
+foreach(`itype',(short,int,uint,float,double,longlong,ulonglong),`TEST_ERANGE_PUT(ushort, itype)')
+foreach(`itype',(uint,float,double,longlong,ulonglong),`TEST_ERANGE_PUT(int, itype)')
+foreach(`itype',(int,float,double,longlong,ulonglong),`TEST_ERANGE_PUT(uint, itype)')
+TEST_ERANGE_PUT(float, double)
+
+define(`TEST_ERANGE_GET',dnl
+`dnl
+static
+int test_erange_get_$1_$2(char* filename) {
+    int i, err, nerrs=0, ncid, dimid, omode, varid, cdf;
+    $1 wbuf[LEN];
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    /* create a new file */
+    err = ncmpi_create(comm, filename, NC_CLOBBER, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "X", LEN, &dimid); ERR
+    err = ncmpi_def_var(ncid, "var", NC_TYPE($1), 1, &dimid, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    err = ncmpi_inq_format(ncid, &cdf); ERR
+
+    /* write MAX values */
+    for (i=0; i<LEN; i++)
+        wbuf[i] = ($1) ifelse(index(`$1',`u'), 0,`XTYPE_MAX($1)',`ifelse(index(`$2',`u'), 0,`-1', `XTYPE_MAX($1)')');
+    err = PUT_VAR($1)(ncid, varid, wbuf); ERR
+    err = ncmpi_close(ncid); ERR
+
+    /* reopen the file and check the contents of variable */
+    omode = NC_NOWRITE;
+    err = ncmpi_open(comm, filename, omode, info, &ncid); ERR
+    err = ncmpi_inq_varid(ncid, "var", &varid); ERR
+
+    /* get data with ERANGE values */
+    $2 rbuf[LEN];
+    err = GET_VAR($2)(ncid, varid, rbuf);
+    ifelse(`$1',`schar',`ifelse(`$2',`uchar',`if (cdf == NC_FORMAT_CDF2) ERR',`ERR_EXPECT(NC_ERANGE)')',`ERR_EXPECT(NC_ERANGE)')
+
+    for (i=0; i<LEN; i++) {
+        $2 expect = ($2)NC_FILL_VALUE($2);
+        ifelse(`$1',`schar',`ifelse(`$2',`uchar',`if (cdf != NC_FORMAT_CDF5) expect = ($2)wbuf[i];')')
+        if (rbuf[i] != expect) {
+            printf("Error at %s line %d: expect rbuf[%d]=IFMT($2) but got IFMT($2)\n",
+                   __func__,__LINE__,i,expect,rbuf[i]);
+            nerrs++;
+        }
+    }
+    err = ncmpi_close(ncid); ERR
+    return nerrs;
+}
+')dnl
+
+foreach(`itype',(uchar,short,ushort,int,uint,float,double,longlong,ulonglong),`TEST_ERANGE_GET(itype,schar)')
+foreach(`itype',(schar,short,ushort,int,uint,float,double,longlong,ulonglong),`TEST_ERANGE_GET(itype,uchar)')
+foreach(`itype',(ushort,int,uint,float,double,longlong,ulonglong),`TEST_ERANGE_GET(itype,short)')
+foreach(`itype',(short,int,uint,float,double,longlong,ulonglong),`TEST_ERANGE_GET(itype,ushort)')
+foreach(`itype',(uint,float,double,longlong,ulonglong),`TEST_ERANGE_GET(itype,int)')
+foreach(`itype',(int,float,double,longlong,ulonglong),`TEST_ERANGE_GET(itype,uint)')
+TEST_ERANGE_GET(double, float)
+
+int main(int argc, char** argv) {
+    char filename[256];
+    int err, nerrs=0, rank, fillv;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for checking for type conflict ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    /*---- CDF-2 format -----------------------------------------------------*/
+    /* ncmpi_set_default_format(NC_FORMAT_CLASSIC, NULL); */
+    ncmpi_set_default_format(NC_FORMAT_CDF2, NULL);
+
+    nerrs += test_default_fill_mode(filename);
+
+    foreach(`itype', (CDF2_ITYPE_LIST), `
+    _CAT(`nerrs += test_default_fill_',itype)'`(filename);')
+
+    fillv=99;
+    foreach(`itype', (CDF2_ITYPE_LIST), `
+    _CAT(`nerrs += test_user_fill_',itype)'`(filename, (itype)fillv);')
+
+    /* test put ERANGE values */
+    foreach(`itype', (uchar,short,int,float,double), `
+    _CAT(`nerrs += test_erange_put_schar_',itype)'`(filename);')
+
+    foreach(`itype', (ushort,int,uint,float,double), `
+    _CAT(`nerrs += test_erange_put_short_',itype)'`(filename);')
+
+    foreach(`itype', (float,double), `
+    _CAT(`nerrs += test_erange_put_int_',itype)'`(filename);')
+
+    nerrs += test_erange_put_float_double(filename);
+
+    /* test get ERANGE values */
+    foreach(`itype', (short,int,float,double), `
+    _CAT(`nerrs += test_erange_get_',itype)'`_schar(filename);')
+
+    foreach(`itype', (schar,short,int,float,double), `
+    _CAT(`nerrs += test_erange_get_',itype)'`_uchar(filename);')
+
+    foreach(`itype', (int,float,double), `
+    _CAT(`nerrs += test_erange_get_',itype)'`_short(filename);')
+
+    foreach(`itype', (float,double), `
+    _CAT(`nerrs += test_erange_get_',itype)'`_int(filename);')
+
+    nerrs += test_erange_get_double_float(filename);
+
+    /*---- CDF-5 format -----------------------------------------------------*/
+    ncmpi_set_default_format(NC_FORMAT_CDF5, NULL);
+
+    nerrs += test_default_fill_mode(filename);
+
+    foreach(`itype', (ITYPE_LIST), `
+    _CAT(`nerrs += test_default_fill_',itype)'`(filename);')
+
+    fillv=99;
+    foreach(`itype', (ITYPE_LIST), `
+    _CAT(`nerrs += test_user_fill_',itype)'`(filename, (itype)fillv);')
+
+    /* test put ERANGE values */
+    foreach(`itype', (uchar,short,ushort,int,uint,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_put_schar_',itype)'`(filename);')
+
+    foreach(`itype', (schar,short,ushort,int,uint,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_put_uchar_',itype)'`(filename);')
+
+    foreach(`itype', (ushort,int,uint,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_put_short_',itype)'`(filename);')
+
+    foreach(`itype', (short,int,uint,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_put_ushort_',itype)'`(filename);')
+
+    foreach(`itype', (uint,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_put_int_',itype)'`(filename);')
+
+    foreach(`itype', (int,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_put_uint_',itype)'`(filename);')
+
+    nerrs += test_erange_put_float_double(filename);
+
+    /* test get ERANGE values */
+    foreach(`itype', (uchar,short,ushort,int,uint,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_get_',itype)'`_schar(filename);')
+
+    foreach(`itype', (schar,short,ushort,int,uint,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_get_',itype)'`_uchar(filename);')
+
+    foreach(`itype', (ushort,int,uint,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_get_',itype)'`_short(filename);')
+
+    foreach(`itype', (short,int,uint,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_get_',itype)'`_ushort(filename);')
+
+    foreach(`itype', (uint,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_get_',itype)'`_int(filename);')
+
+    foreach(`itype', (int,float,double,longlong,ulonglong), `
+    _CAT(`nerrs += test_erange_get_',itype)'`_uint(filename);')
+
+    nerrs += test_erange_get_double_float(filename);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/flexible.c b/test/testcases/flexible.c
index d4085ab..6104321 100644
--- a/test/testcases/flexible.c
+++ b/test/testcases/flexible.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: flexible.c 2133 2015-09-26 19:16:01Z wkliao $
+ *  $Id: flexible.c 2399 2016-04-17 18:59:32Z wkliao $
  */
 
 /*
@@ -27,8 +27,8 @@
  *    data:
  * 
  *    var =
- *      1, 1, 1, 1, 1,
- *      0, 0, 0, 0, 0 ;
+ *      11, 11, 11, 11, 11,
+ *      10, 10, 10, 10, 10 ;
  *    }
  */
 
@@ -85,7 +85,7 @@ int main(int argc, char **argv) {
     err = ncmpi_enddef(ncid); ERR
 
     /* initialize the contents of the array */
-    for (j=0; j<NY; j++) for (i=0; i<NX; i++) buf[j][i] = j;
+    for (j=0; j<NY; j++) for (i=0; i<NX; i++) buf[j][i] = j+10;
 
     /* construct an MPI derived data type for swapping 1st row with 2nd row */
     blocklengths[0] = blocklengths[1] = NX;
@@ -109,7 +109,7 @@ int main(int argc, char **argv) {
     /* check if the contents of buf are altered */
     for (j=0; j<NY; j++)
         for (i=0; i<NX; i++)
-            if (buf[j][i] != j)
+            if (buf[j][i] != j+10)
                 printf("buf[%d][%d] != %d\n",j,i,buf[j][i]);
  
     /* check if root process can write to file header in data mode */
@@ -137,7 +137,7 @@ int main(int argc, char **argv) {
     for (j=0; j<2; j++) {
         int val = (j == 0) ? 1 : 0;
         for (i=0; i<NX; i++)
-            if (buf[j][i] != val) {
+            if (buf[j][i] != val+10) {
                 printf("Unexpected buf[%d][%d]=%d != %d\n",j,i,buf[j][i],val);
                 nerrs++;
             }
diff --git a/test/testcases/flexible2.c b/test/testcases/flexible2.c
index 8cf89e3..6c61b2b 100644
--- a/test/testcases/flexible2.c
+++ b/test/testcases/flexible2.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: flexible2.c 2133 2015-09-26 19:16:01Z wkliao $ */
+/* $Id: flexible2.c 2399 2016-04-17 18:59:32Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *
@@ -41,33 +41,33 @@
  *    data:
  *
  *     var_zy =
- *      0, 0, 0, 0, 0,
- *      0, 0, 0, 0, 0,
- *      0, 0, 0, 0, 0,
- *      0, 0, 0, 0, 0,
- *      0, 0, 0, 0, 0,
- *      1, 1, 1, 1, 1,
- *      1, 1, 1, 1, 1,
- *      1, 1, 1, 1, 1,
- *      1, 1, 1, 1, 1,
- *      1, 1, 1, 1, 1,
- *      2, 2, 2, 2, 2,
- *      2, 2, 2, 2, 2,
- *      2, 2, 2, 2, 2,
- *      2, 2, 2, 2, 2,
- *      2, 2, 2, 2, 2,
- *      3, 3, 3, 3, 3,
- *      3, 3, 3, 3, 3,
- *      3, 3, 3, 3, 3,
- *      3, 3, 3, 3, 3,
- *      3, 3, 3, 3, 3 ;
+ *      10, 10, 10, 10, 10,
+ *      10, 10, 10, 10, 10,
+ *      10, 10, 10, 10, 10,
+ *      10, 10, 10, 10, 10,
+ *      10, 10, 10, 10, 10,
+ *      11, 11, 11, 11, 11,
+ *      11, 11, 11, 11, 11,
+ *      11, 11, 11, 11, 11,
+ *      11, 11, 11, 11, 11,
+ *      11, 11, 11, 11, 11,
+ *      12, 12, 12, 12, 12,
+ *      12, 12, 12, 12, 12,
+ *      12, 12, 12, 12, 12,
+ *      12, 12, 12, 12, 12,
+ *      12, 12, 12, 12, 12,
+ *      13, 13, 13, 13, 13,
+ *      13, 13, 13, 13, 13,
+ *      13, 13, 13, 13, 13,
+ *      13, 13, 13, 13, 13,
+ *      13, 13, 13, 13, 13 ;
  *
  *     var_yx =
- *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
- *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
- *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
- *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
- *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 ;
+ *      10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+ *      10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+ *      10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+ *      10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+ *      10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13 ;
  *    }
  *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -145,7 +145,7 @@ int main(int argc, char** argv)
 
     int buffer_len = (NZ+2*ghost_len) * (NY+2*ghost_len);
     buf_zy = (int*) malloc(buffer_len * sizeof(int));
-    for (i=0; i<buffer_len; i++) buf_zy[i] = rank;
+    for (i=0; i<buffer_len; i++) buf_zy[i] = rank+10;
 
     start[0] = NZ * rank; start[1] = 0;
     count[0] = NZ;        count[1] = NY;
@@ -155,7 +155,7 @@ int main(int argc, char** argv)
 
     /* check the contents of put buffer */
     for (i=0; i<buffer_len; i++) {
-        if (buf_zy[i] != rank) {
+        if (buf_zy[i] != rank+10) {
             printf("Error put buffer[%d] is altered\n",i);
             nerrs++;
         }
@@ -179,7 +179,7 @@ int main(int argc, char** argv)
                 }
             }
             else {
-                if (buf_zy[index] != rank) {
+                if (buf_zy[index] != rank+10) {
                     printf("Unexpected get buffer[%d][%d]=%d\n",
                            i,j,buf_zy[index]);
                     nerrs++;
@@ -204,7 +204,7 @@ int main(int argc, char** argv)
 
     buffer_len = (NY+2*ghost_len) * (NX+2*ghost_len);
     buf_yx = (double*) malloc(buffer_len * sizeof(double));
-    for (i=0; i<buffer_len; i++) buf_yx[i] = rank;
+    for (i=0; i<buffer_len; i++) buf_yx[i] = rank+10;
 
     start[0] = 0;  start[1] = NX * rank;
     count[0] = NY; count[1] = NX;
@@ -217,7 +217,7 @@ int main(int argc, char** argv)
 
     /* check the contents of put buffer */
     for (i=0; i<buffer_len; i++) {
-        if (buf_yx[i] != rank) {
+        if (buf_yx[i] != rank+10) {
             printf("Error iput buffer[%d]=%f is altered\n",i,buf_yx[i]);
             nerrs++;
         }
@@ -244,7 +244,7 @@ int main(int argc, char** argv)
                 }
             }
             else {
-                if (buf_yx[index] != rank) {
+                if (buf_yx[index] != rank+10) {
                     printf("Unexpected get buffer[%d][%d]=%f\n",
                            i,j,buf_yx[index]);
                     nerrs++;
diff --git a/test/testcases/inq_num_varsf.f90 b/test/testcases/inq_num_varsf.f90
index 3f2fa4d..c35284f 100644
--- a/test/testcases/inq_num_varsf.f90
+++ b/test/testcases/inq_num_varsf.f90
@@ -2,7 +2,7 @@
 !   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: inq_num_varsf.f90 2205 2015-11-28 20:41:50Z wkliao $
+! $Id: inq_num_varsf.f90 2512 2016-09-29 01:29:37Z wkliao $
 
 !
 ! This program tests if one can get the number of record variables and
@@ -151,15 +151,18 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err == NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, ierr)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
                   sum_size/1048576, ' MiB yet to be freed'
           endif
 
-          msg = '*** TESTING F90 '//trim(cmd)//' for no. record/fixed variables'
-          if (rank .eq. 0) call pass_fail(nerrs, msg)
+          if (rank .eq. 0) then
+              msg = '*** TESTING F90 '//trim(cmd)// &
+                    ' for no. record/fixed variables'
+              call pass_fail(nerrs, msg)
+          endif
 
  999      call MPI_Finalize(ierr)
       end program main
diff --git a/test/testcases/inq_recsizef.f90 b/test/testcases/inq_recsizef.f90
index f78a7fa..f2730c7 100644
--- a/test/testcases/inq_recsizef.f90
+++ b/test/testcases/inq_recsizef.f90
@@ -2,7 +2,7 @@
 !   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: inq_recsizef.f90 2205 2015-11-28 20:41:50Z wkliao $
+! $Id: inq_recsizef.f90 2512 2016-09-29 01:29:37Z wkliao $
 
 !
 ! This program tests if one can get the size of record block correctly.
@@ -127,15 +127,17 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err == NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, ierr)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
                   sum_size/1048576, ' MiB yet to be freed'
           endif
 
-          msg = '*** TESTING F90 '//trim(cmd)//' for inquiring record size'
-          if (rank .eq. 0) call pass_fail(nerrs, msg)
+          if (rank .eq. 0) then
+              msg = '*** TESTING F90 '//trim(cmd)//' for inquiring record size'
+              call pass_fail(nerrs, msg)
+          endif
 
  999      call MPI_Finalize(ierr)
       end program main
diff --git a/test/testcases/last_large_var.c b/test/testcases/last_large_var.c
index 80d0a7b..c03b431 100644
--- a/test/testcases/last_large_var.c
+++ b/test/testcases/last_large_var.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: last_large_var.c 2291 2016-01-03 05:14:45Z wkliao $ */
+/* $Id: last_large_var.c 2454 2016-06-23 19:14:10Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This program tests the special case when there is no record variable, the
@@ -65,7 +65,7 @@ int check_last_var(char *filename)
     err = ncmpi_def_dim(ncid, "YY", 66661, &dimid[2]); ERR
     err = ncmpi_def_dim(ncid, "XX", 66661, &dimid[3]); ERR
 
-    /* define only fixed-size variables */
+    /* define only fixed-size variables and the last one is "big" */
     err = ncmpi_def_var(ncid, "var", NC_INT, 1, dimid+1, &varid); ERR
     err = ncmpi_def_var(ncid, "var_last", NC_FLOAT, 2, dimid+2, &varid); ERR
 
@@ -76,7 +76,54 @@ int check_last_var(char *filename)
 }
 
 static
-int check_rec_var(char *filename)
+int check_fix_var(char *filename)
+{
+    int err, nerrs=0, ncid, cmode, varid, dimid[4];
+
+    /* create a new CDF-1 file ----------------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "X", 536870911, &dimid[0]); ERR
+
+    /* define only fixed-size variables and no one is "big"
+     * make the starting offset of last one > 2GiB (illegal for CDF-1)
+     */
+    err = ncmpi_def_var(ncid, "var1", NC_INT,   1, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var2", NC_FLOAT, 1, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var3", NC_SHORT, 1, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var4", NC_INT,   1, dimid, &varid); ERR
+
+    err = ncmpi_close(ncid);
+    if (err != NC_EVARSIZE) {
+        printf("\nError at line=%d: expecting error code NC_EVARSIZE but got %s\n",__LINE__,nc_err_code_name(err));
+        nerrs++;
+    }
+
+    /* create a new CDF-2 file ----------------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_OFFSET;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "X", 536870911, &dimid[0]); ERR
+
+    /* define only fixed-size variables and no one is "big"
+     * make the starting offset of last one > 2GiB (legal for CDF-2)
+     */
+    err = ncmpi_def_var(ncid, "var1", NC_INT,   1, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var2", NC_FLOAT, 1, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var3", NC_SHORT, 1, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var4", NC_INT,   1, dimid, &varid); ERR
+
+    err = ncmpi_enddef(ncid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    return nerrs;
+}
+
+static
+int check_fix_rec_var(char *filename)
 {
     int err, nerrs=0, ncid, cmode, varid, dimid[4];
 
@@ -108,6 +155,77 @@ int check_rec_var(char *filename)
     return nerrs;
 }
 
+/* http://www.unidata.ucar.edu/software/netcdf/docs/file_structure_and_performance.html#classic_format_limitations
+ * If you use the unlimited dimension, record variables may exceed 2 GiB in
+ * size, as long as the offset of the start of each record variable within a
+ * record is less than 2 GiB - 4.
+ */
+static
+int check_rec_var(char *filename, int cmode)
+{
+    int err, nerrs=0, ncid, varid, dimid[3];
+
+    /* create a new file ---------------------------------------------------*/
+    cmode |= NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "Z", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "Y", 66661,        &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "X", 66661,        &dimid[2]); ERR
+
+    /* define record variables: last one is large */
+    err = ncmpi_def_var(ncid, "var",       NC_INT,   1, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var_large", NC_FLOAT, 3, dimid, &varid); ERR
+
+    err = ncmpi_close(ncid); ERR
+
+    /* create a new file ---------------------------------------------------*/
+    cmode |= NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "Z", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "Y", 1048576, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "X", 1000, &dimid[2]); ERR
+
+    /* define record variables: both starting offsets are < 2^31-4 */
+    err = ncmpi_def_var(ncid, "var1", NC_SHORT, 3, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var2", NC_SHORT, 3, dimid, &varid); ERR
+
+    err = ncmpi_close(ncid); ERR
+
+    /* create a new file ---------------------------------------------------*/
+    cmode |= NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "Z", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "Y", 1048576, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "X", 1024, &dimid[2]); ERR
+
+    /* define record variables: some starting offsets are > 2^31-4 */
+    err = ncmpi_def_var(ncid, "var1", NC_SHORT, 3, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var2", NC_SHORT, 3, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var3", NC_SHORT, 3, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var4", NC_SHORT, 3, dimid, &varid); ERR
+
+    err = ncmpi_close(ncid);
+    if (cmode & NC_64BIT_OFFSET || cmode & NC_64BIT_DATA) ERR
+    else if (err != NC_EVARSIZE) {
+        printf("\nError at line=%d: expecting error code NC_EVARSIZE but got %s\n",__LINE__,nc_err_code_name(err));
+        nerrs++;
+    }
+
+    return nerrs;
+}
+
+/* http://www.unidata.ucar.edu/software/netcdf/docs/file_structure_and_performance.html#classic_format_limitations
+ * If you don't use the unlimited dimension, only one variable can exceed 2 GiB
+ * in size, but it can be as large as the underlying file system permits. It
+ * must be the last variable in the dataset, and the offset to the beginning of
+ * this variable must be less than about 2 GiB.
+ */
 static
 int check_not_last_var(char *filename)
 {
@@ -124,8 +242,8 @@ int check_not_last_var(char *filename)
     err = ncmpi_def_dim(ncid, "XX", 66661, &dimid[3]); ERR
 
     /* the large variable is not the last */
-    err = ncmpi_def_var(ncid, "var_last", NC_FLOAT, 2, dimid+2, &varid); ERR
-    err = ncmpi_def_var(ncid, "var", NC_INT, 1, dimid+1, &varid); ERR
+    err = ncmpi_def_var(ncid, "var_large", NC_FLOAT, 2, dimid+2, &varid); ERR
+    err = ncmpi_def_var(ncid, "var",       NC_INT,   1, dimid+1, &varid); ERR
 
     err = ncmpi_enddef(ncid);
     if (err != NC_EVARSIZE) {
@@ -232,8 +350,12 @@ int main(int argc, char** argv)
         printf("%-66s ------ ", cmd_str); fflush(stdout);
     }
 
+    nerrs += check_fix_var(filename);
     nerrs += check_last_var(filename);
-    nerrs += check_rec_var(filename);
+    nerrs += check_fix_rec_var(filename);
+    nerrs += check_rec_var(filename, 0);
+    nerrs += check_rec_var(filename, NC_64BIT_OFFSET);
+    nerrs += check_rec_var(filename, NC_64BIT_DATA);
     nerrs += check_not_last_var(filename);
     nerrs += check_add_var(filename);
     nerrs += check_var_offset(filename);
diff --git a/test/testcases/modes.c b/test/testcases/modes.c
index 8e9ec21..636dbea 100644
--- a/test/testcases/modes.c
+++ b/test/testcases/modes.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: modes.c 2219 2015-12-11 22:30:03Z wkliao $ */
+/* $Id: modes.c 2474 2016-09-05 23:13:05Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This program tests if the correct error codes are returns given various
@@ -33,6 +33,13 @@
                __LINE__,nc_err_code_name(err_no),nc_err_code_name(err)); \
     }
 
+#define EXPECT_ERR2(err_no1, err_no2) \
+    if (err != err_no1 && err != err_no2) { \
+        nerrs++; \
+        printf("Error at line %d: expect error code %s but got %s\n", \
+               __LINE__,nc_err_code_name(err_no1),nc_err_code_name(err)); \
+    }
+
 static
 int check_modes(char *filename)
 {
@@ -70,7 +77,8 @@ int check_modes(char *filename)
     /* Collectively opening a non-existing file for read, expect error code
      * NC_ENOENT on all processes */
     err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid);
-    EXPECT_ERR(NC_ENOENT)
+    /* older version of OpenMPI and MPICH may return MPI_ERR_IO instead of MPI_ERR_NO_SUCH_FILE */
+    EXPECT_ERR2(NC_ENOENT, NC_EFILE)
 
     file_exist = 0;
     if (rank == 0 && access(filename, F_OK) == 0) file_exist = 1;
@@ -87,7 +95,8 @@ int check_modes(char *filename)
     /* Collectively opening a non-existing file for write, expect error code
      * NC_ENOENT on all processes */
     err = ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid);
-    EXPECT_ERR(NC_ENOENT)
+    /* older version of OpenMPI and MPICH may return MPI_ERR_IO instead of MPI_ERR_NO_SUCH_FILE */
+    EXPECT_ERR2(NC_ENOENT, NC_EFILE)
 
     file_exist = 0;
     if (rank == 0 && access(filename, F_OK) == 0) file_exist = 1;
diff --git a/test/testcases/ncmpi_vars_null_stride.c b/test/testcases/ncmpi_vars_null_stride.c
index de69c0c..d0d302f 100644
--- a/test/testcases/ncmpi_vars_null_stride.c
+++ b/test/testcases/ncmpi_vars_null_stride.c
@@ -2,11 +2,12 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: ncmpi_vars_null_stride.c 2133 2015-09-26 19:16:01Z wkliao $
+ *  $Id: ncmpi_vars_null_stride.c 2453 2016-06-23 18:59:04Z wkliao $
  */
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>  /* memset() */
 #include <mpi.h>
 #include <pnetcdf.h>
 
@@ -18,14 +19,27 @@
     goto fn_exit; \
 }
 
-#define NDIMS 1
+/* check if user put buffer contents altered */
+#define CHECK_PUT_BUF \
+    for (i=0; i<NY*NX; i++) { \
+        if (buf[i] != rank+10) { \
+            printf("Error at line %d: user put buffer[%d] altered from %d to %d\n", \
+                   __LINE__, i, rank+10, buf[i]); \
+            nerrs++; \
+        } \
+    }
+
+#define NDIMS 2
+#define NY 4
+#define NX 2
+
 int main(int argc, char **argv)
 {
-    int err, nerrs=0, ncfile, dimid, varid, ndims=NDIMS;
-    int i, nprocs, rank;
+    int err, nerrs=0, ncid, dimid[NDIMS], varid[5], ndims=NDIMS;
+    int i, j, k, nprocs, rank, req, *buf;
     MPI_Offset start[NDIMS] = {0};
     MPI_Offset count[NDIMS] = {0};
-    int buf[512];
+    MPI_Offset stride[NDIMS] = {0};
     char *filename="testfile.nc";
 
     MPI_Init(&argc, &argv);
@@ -45,26 +59,210 @@ int main(int argc, char **argv)
         printf("%-66s ------ ", cmd_str); fflush(stdout);
     }
 
-    err = ncmpi_create(MPI_COMM_WORLD, filename, 0, MPI_INFO_NULL, &ncfile);
+    err = ncmpi_create(MPI_COMM_WORLD, filename, 0, MPI_INFO_NULL, &ncid);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_def_dim(ncid, "X", nprocs*NX, &dimid[1]);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_def_var(ncid, "v0", NC_INT, ndims, dimid, &varid[0]);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_def_var(ncid, "v1", NC_INT, ndims, dimid, &varid[1]);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_def_var(ncid, "v2", NC_INT, ndims, dimid, &varid[2]);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_def_var(ncid, "v3", NC_INT, ndims, dimid, &varid[3]);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_def_var(ncid, "v4", NC_INT, ndims, dimid, &varid[4]);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_enddef(ncid);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    start[0] = 0;
+    start[1] = rank*NX;
+    count[0] = NY;
+    count[1] = NX;
+    buf = (int*) malloc((size_t)NY * NX * sizeof(int));
+    for (i=0; i<NY*NX; i++) buf[i] = rank+10;
+
+    err = ncmpi_put_vara_int_all(ncid, varid[0], start, count, buf);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+    CHECK_PUT_BUF
+
+    err = ncmpi_put_vars_int_all(ncid, varid[1], start, count, NULL, buf);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+    CHECK_PUT_BUF
+
+    start[0] = 0;
+    start[1] = rank;
+    count[0] = NY;
+    count[1] = NX;
+    stride[0] = 1;
+    stride[1] = nprocs;
+    err = ncmpi_put_vars_int_all(ncid, varid[2], start, count, stride, buf);
     if (err != NC_NOERR) HANDLE_ERROR(err)
+    CHECK_PUT_BUF
 
-    err = ncmpi_def_dim(ncfile, "d1", nprocs, &dimid);
+    /* test bput_vars */
+    err = ncmpi_buffer_attach(ncid, NY*NX*sizeof(int));
     if (err != NC_NOERR) HANDLE_ERROR(err)
 
-    err = ncmpi_def_var(ncfile, "v1", NC_INT, ndims, &dimid, &varid);
+    start[0] = 0;
+    start[1] = rank*NX;
+    count[0] = NY;
+    count[1] = NX;
+    err = ncmpi_bput_vars_int(ncid, varid[3], start, count, NULL, buf, &req);
     if (err != NC_NOERR) HANDLE_ERROR(err)
 
-    err = ncmpi_enddef(ncfile);
+    err = ncmpi_wait_all(ncid, 1, &req, NULL);
     if (err != NC_NOERR) HANDLE_ERROR(err)
+    CHECK_PUT_BUF
 
-    start[0] = rank;
-    count[0] = 1;
-    for (i=0; i<512; i++) buf[i] = rank;
-    err = ncmpi_put_vars_int_all(ncfile, varid, start, count, NULL, buf);
+    start[0] = 0;
+    start[1] = rank;
+    count[0] = NY;
+    count[1] = NX;
+    stride[0] = 1;
+    stride[1] = nprocs;
+    err = ncmpi_bput_vars_int(ncid, varid[4], start, count, stride, buf, &req);
     if (err != NC_NOERR) HANDLE_ERROR(err)
 
-    err = ncmpi_close(ncfile);
+    err = ncmpi_wait_all(ncid, 1, &req, NULL);
     if (err != NC_NOERR) HANDLE_ERROR(err)
+    CHECK_PUT_BUF
+    free(buf);
+
+    err = ncmpi_buffer_detach(ncid);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    buf = (int*) malloc((size_t)NY * NX * nprocs * sizeof(int));
+    memset(buf, 0, (size_t)NY * NX * nprocs * sizeof(int));
+    err = ncmpi_get_var_int_all(ncid, varid[0], buf);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    /* check read buffer contents */
+    /*  v0 =
+     *    10, 10, 11, 11, 12, 12, 13, 13,
+     *    10, 10, 11, 11, 12, 12, 13, 13,
+     *    10, 10, 11, 11, 12, 12, 13, 13,
+     *    10, 10, 11, 11, 12, 12, 13, 13 ;
+     */
+    for (i=0; i<NY; i++) {
+        for (j=0; j<nprocs; j++) {
+            for (k=0; k<NX; k++) {
+                if (buf[i*nprocs*NX+j*NX+k] != j+10) {
+                    printf("Error at line %d: expected buffer[%d]=%d but got %d\n",
+                           __LINE__,i*nprocs*NX+j*NX+k, j+10, buf[i*nprocs*NX+j*NX+k]);
+                    nerrs++;
+                }
+            }
+        }
+    }
+
+    memset(buf, 0, (size_t)NY * NX * nprocs * sizeof(int));
+    err = ncmpi_get_var_int_all(ncid, varid[1], buf);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    /* check read buffer contents */
+    /*  v1 =
+     *    10, 10, 11, 11, 12, 12, 13, 13,
+     *    10, 10, 11, 11, 12, 12, 13, 13,
+     *    10, 10, 11, 11, 12, 12, 13, 13,
+     *    10, 10, 11, 11, 12, 12, 13, 13 ;
+     */
+    for (i=0; i<NY; i++) {
+        for (j=0; j<nprocs; j++) {
+            for (k=0; k<NX; k++) {
+                if (buf[i*nprocs*NX+j*NX+k] != j+10) {
+                    printf("Error at line %d: expected buffer[%d]=%d but got %d\n",
+                           __LINE__,i*nprocs*NX+j*NX+k, j+10, buf[i*nprocs*NX+j*NX+k]);
+                    nerrs++;
+                }
+            }
+        }
+    }
+
+    memset(buf, 0, (size_t)NY * NX * nprocs * sizeof(int));
+    err = ncmpi_get_var_int_all(ncid, varid[2], buf);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    /* check read buffer contents */
+    /*  v2 =
+     *    10, 11, 12, 13, 10, 11, 12, 13,
+     *    10, 11, 12, 13, 10, 11, 12, 13,
+     *    10, 11, 12, 13, 10, 11, 12, 13,
+     *    10, 11, 12, 13, 10, 11, 12, 13 ;
+     */
+    for (i=0; i<NY; i++) {
+        for (k=0; k<NX; k++) {
+            for (j=0; j<nprocs; j++) {
+                if (buf[i*nprocs*NX+k*nprocs+j] != j+10) {
+                    printf("Error at line %d: expected buffer[%d]=%d but got %d\n",
+                           __LINE__,i*nprocs*NX+k*nprocs+j, j+10, buf[i*nprocs*NX+k*nprocs+j]);
+                    nerrs++;
+                }
+            }
+        }
+    }
+
+    memset(buf, 0, (size_t)NY * NX * nprocs * sizeof(int));
+    err = ncmpi_get_var_int_all(ncid, varid[3], buf);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    /* check read buffer contents */
+    /*  v3 =
+     *    10, 10, 11, 11, 12, 12, 13, 13,
+     *    10, 10, 11, 11, 12, 12, 13, 13,
+     *    10, 10, 11, 11, 12, 12, 13, 13,
+     *    10, 10, 11, 11, 12, 12, 13, 13 ;
+     */
+    for (i=0; i<NY; i++) {
+        for (j=0; j<nprocs; j++) {
+            for (k=0; k<NX; k++) {
+                if (buf[i*nprocs*NX+j*NX+k] != j+10) {
+                    printf("Error at line %d: expected buffer[%d]=%d but got %d\n",
+                           __LINE__,i*nprocs*NX+j*NX+k, j+10, buf[i*nprocs*NX+j*NX+k]);
+                    nerrs++;
+                }
+            }
+        }
+    }
+
+    memset(buf, 0, (size_t)NY * NX * nprocs * sizeof(int));
+    err = ncmpi_get_var_int_all(ncid, varid[4], buf);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    /* check read buffer contents */
+    /*  v4 =
+     *    10, 11, 12, 13, 10, 11, 12, 13,
+     *    10, 11, 12, 13, 10, 11, 12, 13,
+     *    10, 11, 12, 13, 10, 11, 12, 13,
+     *    10, 11, 12, 13, 10, 11, 12, 13 ;
+     */
+    for (i=0; i<NY; i++) {
+        for (k=0; k<NX; k++) {
+            for (j=0; j<nprocs; j++) {
+                if (buf[i*nprocs*NX+k*nprocs+j] != j+10) {
+                    printf("Error at line %d: expected buffer[%d]=%d but got %d\n",
+                           __LINE__,i*nprocs*NX+k*nprocs+j, j+10, buf[i*nprocs*NX+k*nprocs+j]);
+                    nerrs++;
+                }
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    free(buf);
 
     /* check if PnetCDF freed all internal malloc */
     MPI_Offset malloc_size, sum_size;
diff --git a/test/testcases/put_parameter.f b/test/testcases/put_parameter.f
index 902e024..fd0f33e 100644
--- a/test/testcases/put_parameter.f
+++ b/test/testcases/put_parameter.f
@@ -3,7 +3,7 @@
 !   Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: put_parameter.f 2224 2015-12-16 06:10:36Z wkliao $
+! $Id: put_parameter.f 2512 2016-09-29 01:29:37Z wkliao $
 
 ! This example tests PnetCDF's avoiding in-place Endianness byte swap when
 ! the user's write buffer is immutable, i.e. defined as PARAMETER.
@@ -149,7 +149,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8,
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
@@ -157,9 +157,11 @@
      +            sum_size/1048576, ' MiB yet to be freed'
           endif
 
-          msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
-     +          ' for using immutable write buf '
-          if (rank .eq. 0) call pass_fail(nerrs, msg)
+          if (rank .eq. 0) then
+              msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
+     +              ' for using immutable write buf '
+              call pass_fail(nerrs, msg)
+          endif
 
  999      call MPI_Finalize(ierr)
       end ! program main
diff --git a/test/testcases/redef1.c b/test/testcases/redef1.c
index 2658c50..d397813 100644
--- a/test/testcases/redef1.c
+++ b/test/testcases/redef1.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: redef1.c 2133 2015-09-26 19:16:01Z wkliao $
+ *  $Id: redef1.c 2465 2016-09-01 18:07:56Z wkliao $
  */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -141,6 +141,7 @@ int main(int argc, char** argv)
     PNCDF_Error(err, "close")
 
     err = ncmpi_open(comm, filename, NC_WRITE, MPI_INFO_NULL, &ncid);
+    PNCDF_Error(err, "ncmpi_open")
 
     err = ncmpi_redef(ncid);
     PNCDF_Error(err, "redef")
diff --git a/test/testcases/scalar.c b/test/testcases/scalar.c
new file mode 100644
index 0000000..19403fb
--- /dev/null
+++ b/test/testcases/scalar.c
@@ -0,0 +1,124 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: scalar.c 2347 2016-03-09 23:00:53Z wkliao $
+ *
+ *  Check if arguments start, count, stride, and imap are properly ignored
+ *  when get/put a scalar variable.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define PRINT_ERR_ON_SCREEN
+
+#define ERRCODE 2
+#define ERR {if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__, ncmpi_strerror(err)); nerrs++;}}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    int err, nerrs=0, rank, nprocs, verbose, ncid, varid;
+    MPI_Offset start[1], count[1], stride[1], imap[1];
+    int   buf;
+    char *filename="testfile.nc";
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for get/put scalar variables ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    verbose = 0;
+    if (nprocs > 1 && rank == 0 && verbose)
+        printf("Warning: %s is designed to run on 1 process\n", argv[0]);
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER | NC_64BIT_DATA,
+                       MPI_INFO_NULL, &ncid); ERR
+
+    /* define a scalar variable of integer type */
+    err = ncmpi_def_var(ncid, "scalar_var", NC_INT, 0, NULL, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    buf = 1;
+    start[0] = 1;
+    count[0] = 2;
+    stride[0] = 2;
+    imap[0] = 2;
+
+    /* put */
+    err = ncmpi_put_var1_int_all(ncid, varid, NULL,  &buf); ERR
+    err = ncmpi_put_var1_int_all(ncid, varid, start, &buf); ERR
+
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, &buf); ERR
+    err = ncmpi_put_vara_int_all(ncid, varid, NULL, count, &buf); ERR
+    err = ncmpi_put_vara_int_all(ncid, varid, start, NULL, &buf); ERR
+    err = ncmpi_put_vara_int_all(ncid, varid, NULL, NULL, &buf); ERR
+
+    err = ncmpi_put_vars_int_all(ncid, varid, start, count, stride, &buf); ERR
+    err = ncmpi_put_vars_int_all(ncid, varid, NULL, count, stride, &buf); ERR
+    err = ncmpi_put_vars_int_all(ncid, varid, start, NULL, stride, &buf); ERR
+    err = ncmpi_put_vars_int_all(ncid, varid, start, count, NULL, &buf); ERR
+    err = ncmpi_put_vars_int_all(ncid, varid, NULL, NULL, NULL, &buf); ERR
+
+    err = ncmpi_put_varm_int_all(ncid, varid, start, count, stride, imap, &buf); ERR
+    err = ncmpi_put_varm_int_all(ncid, varid, NULL, NULL, NULL, NULL, &buf); ERR
+
+    /* get */
+    err = ncmpi_get_var1_int_all(ncid, varid, NULL,  &buf); ERR
+    err = ncmpi_get_var1_int_all(ncid, varid, start, &buf); ERR
+
+    err = ncmpi_get_vara_int_all(ncid, varid, start, count, &buf); ERR
+    err = ncmpi_get_vara_int_all(ncid, varid, NULL, count, &buf); ERR
+    err = ncmpi_get_vara_int_all(ncid, varid, start, NULL, &buf); ERR
+    err = ncmpi_get_vara_int_all(ncid, varid, NULL, NULL, &buf); ERR
+
+    err = ncmpi_get_vars_int_all(ncid, varid, start, count, stride, &buf); ERR
+    err = ncmpi_get_vars_int_all(ncid, varid, NULL, count, stride, &buf); ERR
+    err = ncmpi_get_vars_int_all(ncid, varid, start, NULL, stride, &buf); ERR
+    err = ncmpi_get_vars_int_all(ncid, varid, start, count, NULL, &buf); ERR
+    err = ncmpi_get_vars_int_all(ncid, varid, NULL, NULL, NULL, &buf); ERR
+
+    err = ncmpi_get_varm_int_all(ncid, varid, start, count, stride, imap, &buf); ERR
+    err = ncmpi_get_varm_int_all(ncid, varid, NULL, NULL, NULL, NULL, &buf); ERR
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+
+    return (nerrs == 0) ? 0 : 1;
+}
+
diff --git a/test/testcases/test_erange.c b/test/testcases/test_erange.c
index d22199b..f65467a 100644
--- a/test/testcases/test_erange.c
+++ b/test/testcases/test_erange.c
@@ -7,11 +7,19 @@
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  *
- * This program tests NC_ERANGE error code for the following 2 case.
- * 1. get a value of 255 from a NC_UBYTE variable in a netCDF to a memory
- *    buffer of signed char 
- * 2. put a value of -1 of signed char from a in-memory buffer to a NC_UBYTE
- *    variable in a netCDF file
+ * This program tests whether NC_ERANGE error code can be reported correctly.
+ * Note in CDF-1 and CDF-2, a special case is made to NOT report NC_ERANGE
+ * when the variable is of NC_BYTE type and the calling APIs are of uchar. See
+ * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
+ *
+ * In CDF-5, NC_ERANGE is checked for when the external data type mismatches the
+ * internal one.
+ *
+ * The test uses the following 2 case.
+ * 1. get a value of 255 from a NC_UBYTE variable defined in a netCDF file to a
+ *    memory buffer of signed char through e.g. API ncmpi_get_var_schar_all
+ * 2. put a value of -1 of signed char from an in-memory buffer to a NC_UBYTE
+ *    variable defined in a netCDF file
  *
  * The compile and run commands are given below.
  *
@@ -30,54 +38,170 @@
 #define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n",__LINE__,ncmpi_strerror(err));nerrs++;}
 #define EXPECT_ERR if (err != NC_ERANGE) {printf("Error at line %d: expecting NC_ERANGE, but got %d\n",__LINE__,err);nerrs++;}
 
-int main(int argc, char* argv[])
+static
+int test_cdf2(char *filename)
 {
-    char filename[256];
-    int err, nerrs=0, ncid, uc_vid, sc_vid, dimid, rank;
+    int err, nerrs=0, ncid, vid, dimid;
     unsigned char uc;
     signed char sc;
+    int si;
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, MPI_INFO_NULL, &ncid); ERR
+
+    /* for CDF-1 and CDF-2, a special case is made: there is no NC_ERANGE
+     * error can occur converting between NC_BYTE and unsigned char.
+     * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
+     * In brief, NC_BYTE is signed in all signed CDF-2 APIs, and unsigned in
+     * all unsigned APIs. In CDF-2, there is only one unsigned API, _uchar.
+     */
+    uc = 255;
+    err = ncmpi_put_att_uchar(ncid, NC_GLOBAL, "att1", NC_BYTE, 1, &uc); ERR
+    uc = 0; /* initialize with a number that is not 0 */
+    err = ncmpi_get_att_uchar(ncid, NC_GLOBAL, "att1", &uc); ERR
+    if (uc != 255) {
+        printf("Error at line %d: unexpected read value %d (expecting 255)\n",__LINE__,(int)uc);
+        nerrs++;
+    }
+    sc = 3; /* initialize with a number that is not -1 or -0 */
+    /* No NC_ERANGE as the internal and external types are considered the same */
+    err = ncmpi_get_att_schar(ncid, NC_GLOBAL, "att1", &sc); ERR
+    if (   sc != -1     /* 2-complement bit representation */
+        && sc != -0) {  /* 1-complement bit representation */
+        printf("Error at line %d: unexpected read value %d (expecting 255)\n",__LINE__,(int)uc);
+        nerrs++;
+    }
 
-    MPI_Init(&argc, &argv);
-    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    err = ncmpi_def_dim(ncid, "x", 1, &dimid); ERR
+    err = ncmpi_def_var(ncid, "var_byte", NC_BYTE, 1, &dimid, &vid); ERR
+    err = ncmpi_enddef(ncid); ERR
 
-    if (argc > 2) {
-        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
-        MPI_Finalize();
-        return 0;
+    /* No NC_ERANGE should be returned for CDF-1 and 2 */
+    uc = 255;
+    err = ncmpi_put_var_uchar_all(ncid, vid, &uc); ERR
+    uc = 3; /* initialize with a number that is not -1 or -0 */
+    err = ncmpi_get_var_uchar_all(ncid, vid, &uc); ERR
+    if (uc != 255) {
+        printf("Error at line %d: unexpected read value %d (expecting 255)\n",__LINE__,(int)uc);
+        nerrs++;
     }
-    strcpy(filename, "testfile.nc");
-    if (argc == 2) strcpy(filename, argv[1]);
-    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
 
-    if (rank == 0) {
-        char cmd_str[256];
-        sprintf(cmd_str, "*** TESTING C   %s for checking for NC_ERANGE ", argv[0]);
-        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    /* No NC_ERANGE should be returned for CDF-1 and 2 */
+    sc = -128;
+    err = ncmpi_put_var_schar_all(ncid, vid, &sc); ERR
+    sc = 0;
+    err = ncmpi_get_var_schar_all(ncid, vid, &sc); ERR
+    if (sc != -128) {
+        printf("Error at line %d: unexpected read value %d (expecting -128)\n",__LINE__,(int)sc);
+        nerrs++;
+    }
+
+    /* expect NC_ERANGE */
+    si = -129;
+    err = ncmpi_put_var_int_all(ncid, vid, &si); EXPECT_ERR
+    if (si != -129) { /* check if put buffer content is altered */
+        printf("Error at line %d: put buffer content altered %d (expecting -128)\n",__LINE__,si);
+        nerrs++;
+    }
+
+    /* expect NC_ERANGE */
+    si = 256;
+    err = ncmpi_put_var_int_all(ncid, vid, &si); EXPECT_ERR
+    if (si != 256) { /* check if put buffer content is altered */
+        printf("Error at line %d: put buffer content altered %d (expecting 256)\n",__LINE__,si);
+        nerrs++;
     }
 
+    /* expect no error */
+    si = -128;
+    err = ncmpi_put_var_int_all(ncid, vid, &si); ERR
+    si = 0;
+    err = ncmpi_get_var_int_all(ncid, vid, &si); ERR
+    if (si != -128) {
+        printf("Error at line %d: unexpected read value %d (expecting -128)\n",__LINE__,si);
+        nerrs++;
+    }
+
+    err = ncmpi_close(ncid); ERR
+
+    return nerrs;
+}
+
+static
+int test_cdf5(char *filename)
+{
+    int err, nerrs=0, ncid, uc_vid, sc_vid, dimid;
+    unsigned char uc;
+    signed char sc;
+
     err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_DATA, MPI_INFO_NULL, &ncid); ERR
 
-    uc = 255; /* a value should cause NC_ERANGE at ncmpi_get_att_schar() */
+    /* CDF-5 considers NC_BYTE a signed 1-byte integer and NC_UBYTE an
+     * unsigned 1-byte integer. The special case in CDF-2 for skipping
+     * NC_ERANGE checking for converting between NC_BYTE and unsigned
+     * char is no longer held.
+     */
+    uc = 255;
     err = ncmpi_put_att_uchar(ncid, NC_GLOBAL, "att1", NC_UBYTE, 1, &uc); ERR
+
+    /* in CDF-5, get 255 to a schar buffer should result in NC_ERANGE */
     err = ncmpi_get_att_schar(ncid, NC_GLOBAL, "att1", &sc); EXPECT_ERR
 
     sc = -1; /* a value should cause NC_ERANGE */
     err = ncmpi_put_att_schar(ncid, NC_GLOBAL, "att2", NC_UBYTE, 1, &sc); EXPECT_ERR
 
-    err = ncmpi_def_dim(ncid, "x", 2, &dimid); ERR
+    err = ncmpi_def_dim(ncid, "x", 1, &dimid); ERR
     err = ncmpi_def_var(ncid, "var_ubyte", NC_UBYTE, 1, &dimid, &uc_vid); ERR
     err = ncmpi_def_var(ncid, "var_byte",  NC_BYTE,  1, &dimid, &sc_vid); ERR
     err = ncmpi_enddef(ncid); ERR
 
-    uc = 255; /* a value should cause NC_ERANGE at ncmpi_get_var_schar() */
+    uc = 255;
     err = ncmpi_put_var_uchar_all(ncid, uc_vid, &uc); ERR
+
+    /* in CDF-5, get 255 to an schar should result in NC_ERANGE */
     err = ncmpi_get_var_schar_all(ncid, uc_vid, &sc); EXPECT_ERR
 
-    sc = -1; /* a value should cause NC_ERANGE */
+    sc = -1; /* in CDF-5, put -1 to an uchar should result in NC_ERANGE */
     err = ncmpi_put_var_schar_all(ncid, uc_vid, &sc); EXPECT_ERR
 
+    uc = 255; /* in CDF-5, put 255 to a schar should result in NC_ERANGE */
+    err = ncmpi_put_var_uchar_all(ncid, sc_vid, &uc); EXPECT_ERR
+
+    sc = -1;
+    err = ncmpi_put_var_schar_all(ncid, sc_vid, &sc); ERR
+    uc = 0; /* in CDF-5, get -1 to an uchar should result in NC_ERANGE */
+    err = ncmpi_get_var_uchar_all(ncid, sc_vid, &uc); EXPECT_ERR
+
     err = ncmpi_close(ncid); ERR
 
+    return nerrs;
+}
+
+int main(int argc, char* argv[])
+{
+    char filename[256];
+    int err, nerrs=0, rank;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for checking for NC_ERANGE ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    nerrs += test_cdf2(filename);
+    nerrs += test_cdf5(filename);
+
     /* check if PnetCDF freed all internal malloc */
     MPI_Offset malloc_size, sum_size;
     err = ncmpi_inq_malloc_size(&malloc_size);
diff --git a/test/testcases/test_vard.c b/test/testcases/test_vard.c
index 9250d6b..32b6169 100644
--- a/test/testcases/test_vard.c
+++ b/test/testcases/test_vard.c
@@ -2,7 +2,7 @@
  *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
  *  See COPYRIGHT notice in top-level directory.
  *
- *  $Id: test_vard.c 2219 2015-12-11 22:30:03Z wkliao $
+ *  $Id: test_vard.c 2379 2016-03-28 21:43:38Z wkliao $
  */
 
 /*
@@ -154,7 +154,8 @@ int main(int argc, char **argv) {
     int          i, j, err, ncid, varid0, varid1, varid2, dimids[2], nerrs=0;
     int          rank, nprocs, debug=0, blocklengths[2], **buf, *bufptr;
     int          array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
-    MPI_Offset   start[2], count[2];
+    int          buftype_size, expected_put_size, format;
+    MPI_Offset   start[2], count[2], header_size, put_size, new_put_size;
     MPI_Aint     a0, a1, disps[2];
     MPI_Datatype buftype, ghost_buftype, rec_filetype, fix_filetype;
 
@@ -253,18 +254,48 @@ int main(int argc, char **argv) {
     /* initialize the contents of the array */
     for (j=0; j<NY; j++) for (i=0; i<NX; i++) buf[j][i] = rank*100 + j*10 + i;
 
+    /* get header size and put size by far */
+    err = ncmpi_inq_header_size(ncid, &header_size); ERR
+    err = ncmpi_inq_put_size(ncid, &put_size); ERR
+
     /* write the record variable */
     err = ncmpi_put_vard_all(ncid, varid0, rec_filetype, bufptr, 1, buftype); ERR
 
+    /* check if put_size is correctly reported */
+    err = ncmpi_inq_put_size(ncid, &new_put_size); ERR
+    MPI_Type_size(buftype, &buftype_size);
+    err = ncmpi_inq_format(ncid, &format); ERR
+    expected_put_size = buftype_size;
+
+    /* for writing a record variable, root process will update numrec to the
+     * file header */
+    if (rank == 0) expected_put_size += (format == NC_FORMAT_CDF5) ? 8 : 4;
+    if (expected_put_size != new_put_size - put_size) {
+        printf("Error: unexpected put size (%lld) reported, expecting %d\n",
+               new_put_size-put_size, expected_put_size);
+        nerrs++;
+    }
+
     /* check if the contents of buf are altered */
     CHECK_VALUE
 
     /* check if root process can write to file header in data mode */
     err = ncmpi_rename_var(ncid, varid0, "rec_VAR"); ERR
 
+    err = ncmpi_inq_put_size(ncid, &put_size); ERR
+
     /* write the fixed-size variable */
     err = ncmpi_put_vard_all(ncid, varid1, fix_filetype, bufptr, 1, buftype); ERR
 
+    /* check if put_size is correctly reported */
+    err = ncmpi_inq_put_size(ncid, &new_put_size); ERR
+    expected_put_size = buftype_size;
+    if (expected_put_size != new_put_size - put_size) {
+        printf("Error: unexpected put size (%lld) reported, expecting %d\n",
+               new_put_size-put_size, expected_put_size);
+        nerrs++;
+    }
+
     /* check if the contents of buf are altered */
     CHECK_VALUE
  
diff --git a/test/testcases/test_vardf.F b/test/testcases/test_vardf.F
index a25cecf..f5947bd 100644
--- a/test/testcases/test_vardf.F
+++ b/test/testcases/test_vardf.F
@@ -2,7 +2,7 @@
 !   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: test_vardf.F 2236 2015-12-18 03:49:41Z wkliao $
+! $Id: test_vardf.F 2512 2016-09-29 01:29:37Z wkliao $
 
 !
 ! This program tests the vard API.
@@ -376,7 +376,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8,
      +                        MPI_SUM, 0, MPI_COMM_WORLD, ierr)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
@@ -384,8 +384,11 @@
      +            sum_size/1048576, ' MiB yet to be freed'
           endif
 
-          msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//' for vard API '
-          if (rank .eq. 0) call pass_fail(nerrs, msg)
+          if (rank .eq. 0) then
+              msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
+     +              ' for vard API '
+              call pass_fail(nerrs, msg)
+          endif
 
  999      call MPI_Finalize(ierr)
       end ! program main
diff --git a/test/testcases/test_vardf90.f90 b/test/testcases/test_vardf90.f90
index 2fe2ffc..a423d09 100644
--- a/test/testcases/test_vardf90.f90
+++ b/test/testcases/test_vardf90.f90
@@ -2,7 +2,7 @@
 !   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: test_vardf90.f90 2205 2015-11-28 20:41:50Z wkliao $
+! $Id: test_vardf90.f90 2512 2016-09-29 01:29:37Z wkliao $
 
 !
 ! This program tests the vard API.
@@ -357,15 +357,17 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err == NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, ierr)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
                   sum_size/1048576, ' MiB yet to be freed'
           endif
 
-          msg = '*** TESTING F90 '//trim(cmd)//' for vard API '
-          if (rank .eq. 0) call pass_fail(nerrs, msg)
+          if (rank .eq. 0) then
+              msg = '*** TESTING F90 '//trim(cmd)//' for vard API '
+              call pass_fail(nerrs, msg)
+          endif
 
  999      call MPI_Finalize(ierr)
       end program main
diff --git a/test/testcases/varn_int.c b/test/testcases/varn_int.c
index 8394237..81f7bab 100644
--- a/test/testcases/varn_int.c
+++ b/test/testcases/varn_int.c
@@ -4,7 +4,7 @@
  *  See COPYRIGHT notice in top-level directory.
  *
  *********************************************************************/
-/* $Id: varn_int.c 2219 2015-12-11 22:30:03Z wkliao $ */
+/* $Id: varn_int.c 2399 2016-04-17 18:59:32Z wkliao $ */
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * This example tests using a single call of ncmpi_put_varn_int_all() to
@@ -28,16 +28,16 @@
  *    data:
  *
  *     var =
- *       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
- *       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
- *       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
- *       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *       13, 13, 13, 11, 11, 10, 10, 12, 11, 11,
+ *       10, 12, 12, 12, 13, 11, 11, 12, 12, 12,
+ *       11, 11, 12, 13, 13, 13, 10, 10, 11, 11,
+ *       10, 10, 10, 12, 11, 11, 11, 13, 13, 13 ;
  *
  *     rec_var =
- *       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
- *       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
- *       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
- *       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *       13, 13, 13, 11, 11, 10, 10, 12, 11, 11,
+ *       10, 12, 12, 12, 13, 11, 11, 12, 12, 12,
+ *       11, 11, 12, 13, 13, 13, 10, 10, 11, 11,
+ *       10, 10, 10, 12, 11, 11, 11, 13, 13, 13 ;
  *    }
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -59,10 +59,10 @@ static
 int check_contents_for_fail(int *buffer)
 {
     int i, nprocs;
-    int expected[NY*NX] = {3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
-                           0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
-                           1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
-                           0, 0, 0, 2, 1, 1, 1, 3, 3, 3};
+    int expected[NY*NX] = {13, 13, 13, 11, 11, 10, 10, 12, 11, 11,
+                           10, 12, 12, 12, 13, 11, 11, 12, 12, 12,
+                           11, 11, 12, 13, 13, 13, 10, 10, 11, 11,
+                           10, 10, 10, 12, 11, 11, 11, 13, 13, 13};
 
     MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
 
@@ -214,7 +214,7 @@ int main(int argc, char** argv)
     /* allocate I/O buffer and initialize its contents */
     r_buffer = (int*) malloc(NY*NX * sizeof(int));
     buffer   = (int*) malloc(w_len * sizeof(int));
-    for (i=0; i<w_len; i++) buffer[i] = rank;
+    for (i=0; i<w_len; i++) buffer[i] = rank+10;
 
     /* check error code: NC_ENULLSTART */
     err = ncmpi_put_varn_int_all(ncid, varid[0], 1, NULL, NULL, NULL);
@@ -227,6 +227,14 @@ int main(int argc, char** argv)
     err = ncmpi_put_varn_int_all(ncid, varid[0], num_reqs, starts, counts, buffer);
     ERR
 
+    /* check if user put buffer contents altered */
+    for (i=0; i<w_len; i++) {
+        if (buffer[i] != rank+10) {
+            printf("Error: user put buffer[%d] altered from %d to %d\n",
+                   i, rank+10, buffer[i]);
+            nerrs++;
+        }
+    }
     if (nprocs > 4) MPI_Barrier(MPI_COMM_WORLD);
 
     /* read back and check contents */
@@ -245,6 +253,15 @@ int main(int argc, char** argv)
     err = ncmpi_put_varn_int_all(ncid, varid[1], num_reqs, starts, counts, buffer);
     ERR
 
+    /* check if user put buffer contents altered */
+    for (i=0; i<w_len; i++) {
+        if (buffer[i] != rank+10) {
+            printf("Error: user put buffer[%d] altered from %d to %d\n",
+                   i, rank+10, buffer[i]);
+            nerrs++;
+        }
+    }
+
     /* read back using get_var API and check contents */
     memset(r_buffer, 0, NY*NX*sizeof(int));
     err = ncmpi_get_var_int_all(ncid, varid[1], r_buffer);
@@ -257,9 +274,9 @@ int main(int argc, char** argv)
     ERR
 
     for (i=0; i<w_len; i++) {
-        if (buffer[i] != rank) {
+        if (buffer[i] != rank+10) {
             printf("Error at line %d: expecting buffer[%d]=%d but got %d\n",
-                   __LINE__,i,rank,buffer[i]);
+                   __LINE__,i,rank+10,buffer[i]);
             nerrs++;
         }
     }
@@ -281,9 +298,9 @@ int main(int argc, char** argv)
                    __LINE__,i,buffer[i]);
             nerrs++;
         }
-        if (i%2 == 0 && buffer[i] != rank) {
+        if (i%2 == 0 && buffer[i] != rank+10) {
             printf("Error at line %d: expecting buffer[%d]=%d but got %d\n",
-                   __LINE__,i,rank,buffer[i]);
+                   __LINE__,i,rank+10,buffer[i]);
             nerrs++;
         }
     }
diff --git a/test/testcases/varn_intf.f b/test/testcases/varn_intf.f
index 6b925e7..c6b81f6 100644
--- a/test/testcases/varn_intf.f
+++ b/test/testcases/varn_intf.f
@@ -2,7 +2,7 @@
 !   Copyright (C) 2013, Northwestern University
 !   See COPYRIGHT notice in top-level directory.
 !
-! $Id: varn_intf.f 2224 2015-12-16 06:10:36Z wkliao $
+! $Id: varn_intf.f 2512 2016-09-29 01:29:37Z wkliao $
 
 ! This example shows how to use a single call of nfmpi_put_varn_int_all() to
 ! write a sequence of requests with arbitrary array indices and lengths.
@@ -272,7 +272,7 @@
  998      format(A,I13,A)
           err = nfmpi_inq_malloc_size(malloc_size)
           if (err .EQ. NF_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8,
      +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
               if (rank .EQ. 0 .AND. sum_size .GT. 0)
      +            print 998,
@@ -280,8 +280,11 @@
      +            sum_size/1048576, ' MiB yet to be freed'
           endif
 
-          msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//' for varn API '
-          if (rank .eq. 0) call pass_fail(nerrs, msg)
+          if (rank .eq. 0) then
+              msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
+     +              ' for varn API '
+              call pass_fail(nerrs, msg)
+          endif
 
  999      call MPI_Finalize(ierr)
       end ! program main
diff --git a/test/testcases/varn_real.f90 b/test/testcases/varn_real.f90
index 1222b6f..09c9813 100644
--- a/test/testcases/varn_real.f90
+++ b/test/testcases/varn_real.f90
@@ -2,7 +2,7 @@
 !  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
 !  See COPYRIGHT notice in top-level directory.
 !
-! $Id: varn_real.f90 2205 2015-11-28 20:41:50Z wkliao $
+! $Id: varn_real.f90 2512 2016-09-29 01:29:37Z wkliao $
 
 !
 ! This example shows how to use a single call of nf90mpi_put_varn_all()
@@ -283,15 +283,17 @@
  998      format(A,I13,A)
           err = nf90mpi_inq_malloc_size(malloc_size)
           if (err == NF90_NOERR) then
-              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_INTEGER8, &
                               MPI_SUM, 0, MPI_COMM_WORLD, ierr)
               if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
                   'heap memory allocated by PnetCDF internally has ',  &
                   sum_size/1048576, ' MiB yet to be freed'
           endif
 
-          msg = '*** TESTING F90 '//trim(cmd)//' for varn API '
-          if (rank .eq. 0) call pass_fail(nerrs, msg)
+          if (rank .eq. 0) then
+              msg = '*** TESTING F90 '//trim(cmd)//' for varn API '
+              call pass_fail(nerrs, msg)
+          endif
 
  999      call MPI_Finalize(ierr)
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/pnetcdf.git



More information about the debian-science-commits mailing list